@osolmaz/pi-workflows 0.16.2 → 0.16.4

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 (315) hide show
  1. package/README.md +41 -41
  2. package/dist/builtins/monitor.workflow.d.ts +1 -1
  3. package/dist/builtins/monitor.workflow.js +8 -8
  4. package/dist/builtins/pi-agent-group.js +3 -3
  5. package/dist/builtins/pi-agent-group.js.map +1 -1
  6. package/dist/channels/adapter-entry.js +14 -14
  7. package/dist/channels/adapter-entry.js.map +1 -1
  8. package/dist/client/client.d.ts +6 -6
  9. package/dist/client/client.js +27 -27
  10. package/dist/client/client.js.map +1 -1
  11. package/dist/client/protocol.d.ts +4 -1
  12. package/dist/client/protocol.js +17 -11
  13. package/dist/client/protocol.js.map +1 -1
  14. package/dist/client/resolver.d.ts +4 -4
  15. package/dist/client/view.d.ts +1 -1
  16. package/dist/extension/index.d.ts +1 -1
  17. package/dist/extension/index.js +32 -32
  18. package/dist/extension/index.js.map +1 -1
  19. package/dist/extension/recorder.d.ts +1 -1
  20. package/dist/extension/recorder.js +1 -1
  21. package/dist/extension/recorder.js.map +1 -1
  22. package/dist/extension/remote-recorder-store.d.ts +1 -1
  23. package/dist/extension/remote-recorder-store.js +2 -2
  24. package/dist/extension/remote-recorder-store.js.map +1 -1
  25. package/dist/extension/{controller-command.d.ts → resource-manager-command.d.ts} +6 -6
  26. package/dist/extension/{controller-command.js → resource-manager-command.js} +7 -7
  27. package/dist/extension/resource-manager-command.js.map +1 -0
  28. package/dist/extension/session-delivery.d.ts +1 -1
  29. package/dist/extension/session-delivery.js +2 -2
  30. package/dist/extension/session-delivery.js.map +1 -1
  31. package/dist/extension/session-view.d.ts +1 -1
  32. package/dist/extension/session-view.js +1 -1
  33. package/dist/extension/session-view.js.map +1 -1
  34. package/dist/extension/workflow-message-coordinator.d.ts +1 -1
  35. package/dist/extension/workflow-message-coordinator.js +6 -6
  36. package/dist/extension/workflow-message-coordinator.js.map +1 -1
  37. package/dist/resource-managers/conditions.d.ts +6 -0
  38. package/dist/{controllers → resource-managers}/conditions.js +3 -3
  39. package/dist/resource-managers/conditions.js.map +1 -0
  40. package/dist/resource-managers/definition.d.ts +6 -0
  41. package/dist/resource-managers/definition.js +45 -0
  42. package/dist/resource-managers/definition.js.map +1 -0
  43. package/dist/resource-managers/effects.d.ts +15 -0
  44. package/dist/{controllers → resource-managers}/effects.js +2 -2
  45. package/dist/resource-managers/effects.js.map +1 -0
  46. package/dist/resource-managers/errors.d.ts +12 -0
  47. package/dist/resource-managers/errors.js +25 -0
  48. package/dist/resource-managers/errors.js.map +1 -0
  49. package/dist/resource-managers/index.d.ts +12 -0
  50. package/dist/resource-managers/index.js +12 -0
  51. package/dist/resource-managers/index.js.map +1 -0
  52. package/dist/resource-managers/json.js.map +1 -0
  53. package/dist/resource-managers/loader.d.ts +23 -0
  54. package/dist/resource-managers/loader.js +75 -0
  55. package/dist/resource-managers/loader.js.map +1 -0
  56. package/dist/resource-managers/results.d.ts +5 -0
  57. package/dist/resource-managers/results.js.map +1 -0
  58. package/dist/resource-managers/runtime.d.ts +59 -0
  59. package/dist/{controllers/manager.js → resource-managers/runtime.js} +57 -57
  60. package/dist/resource-managers/runtime.js.map +1 -0
  61. package/dist/{controllers → resource-managers}/sqlite.d.ts +44 -44
  62. package/dist/{controllers → resource-managers}/sqlite.js +139 -130
  63. package/dist/resource-managers/sqlite.js.map +1 -0
  64. package/dist/{controllers → resource-managers}/store.d.ts +33 -33
  65. package/dist/{controllers → resource-managers}/store.js.map +1 -1
  66. package/dist/{controllers → resource-managers}/types.d.ts +41 -41
  67. package/dist/{controllers → resource-managers}/types.js.map +1 -1
  68. package/dist/resource-managers/workflows.d.ts +34 -0
  69. package/dist/{controllers → resource-managers}/workflows.js +15 -15
  70. package/dist/resource-managers/workflows.js.map +1 -0
  71. package/dist/server/channel-effects.js.map +1 -0
  72. package/dist/{host → server}/channel-supervisor.d.ts +6 -6
  73. package/dist/{host → server}/channel-supervisor.js +3 -3
  74. package/dist/server/channel-supervisor.js.map +1 -0
  75. package/dist/{host/child-worker-supervisor.d.ts → server/child-runner-supervisor.d.ts} +15 -13
  76. package/dist/{host/child-worker-supervisor.js → server/child-runner-supervisor.js} +6 -5
  77. package/dist/server/child-runner-supervisor.js.map +1 -0
  78. package/dist/{host → server}/processes.d.ts +3 -3
  79. package/dist/{host → server}/processes.js +3 -3
  80. package/dist/server/processes.js.map +1 -0
  81. package/dist/{host → server}/resolver-entry.d.ts +6 -6
  82. package/dist/{host → server}/resolver-entry.js +14 -14
  83. package/dist/server/resolver-entry.js.map +1 -0
  84. package/dist/server/resource-runner-entry.d.ts +2 -0
  85. package/dist/{host/controller-worker-entry.js → server/resource-runner-entry.js} +33 -33
  86. package/dist/server/resource-runner-entry.js.map +1 -0
  87. package/dist/server/resource-runner-protocol.d.ts +36 -0
  88. package/dist/server/resource-runner-protocol.js +49 -0
  89. package/dist/server/resource-runner-protocol.js.map +1 -0
  90. package/dist/server/resource-runner-supervisor.d.ts +21 -0
  91. package/dist/{host/worker-supervisor.js → server/resource-runner-supervisor.js} +17 -17
  92. package/dist/server/resource-runner-supervisor.js.map +1 -0
  93. package/dist/{host → server}/rpc-bridge.d.ts +3 -3
  94. package/dist/{host → server}/rpc-bridge.js +3 -3
  95. package/dist/server/rpc-bridge.js.map +1 -0
  96. package/dist/{host → server}/rpc-executor.d.ts +1 -1
  97. package/dist/{host → server}/rpc-executor.js +3 -3
  98. package/dist/server/rpc-executor.js.map +1 -0
  99. package/dist/{host/host-entry.js → server/server-entry.js} +6 -6
  100. package/dist/server/server-entry.js.map +1 -0
  101. package/dist/{host/runner.d.ts → server/server.d.ts} +39 -38
  102. package/dist/{host/runner.js → server/server.js} +408 -374
  103. package/dist/server/server.js.map +1 -0
  104. package/dist/{host → server}/state.d.ts +25 -25
  105. package/dist/{host → server}/state.js +49 -49
  106. package/dist/server/state.js.map +1 -0
  107. package/dist/{host → server}/view.d.ts +7 -7
  108. package/dist/{host → server}/view.js +13 -13
  109. package/dist/server/view.js.map +1 -0
  110. package/dist/server/workflow-runner-content.d.ts +6 -0
  111. package/dist/server/workflow-runner-content.js +96 -0
  112. package/dist/server/workflow-runner-content.js.map +1 -0
  113. package/dist/{host/worker-entry.d.ts → server/workflow-runner-entry.d.ts} +3 -3
  114. package/dist/{host/worker-entry.js → server/workflow-runner-entry.js} +68 -35
  115. package/dist/server/workflow-runner-entry.js.map +1 -0
  116. package/dist/server/workflow-runner-protocol.d.ts +69 -0
  117. package/dist/server/workflow-runner-protocol.js +176 -0
  118. package/dist/server/workflow-runner-protocol.js.map +1 -0
  119. package/dist/{host/worker-store.d.ts → server/workflow-runner-store.d.ts} +11 -11
  120. package/dist/{host/worker-store.js → server/workflow-runner-store.js} +8 -8
  121. package/dist/server/workflow-runner-store.js.map +1 -0
  122. package/dist/server/workflow-runner-supervisor.d.ts +22 -0
  123. package/dist/server/workflow-runner-supervisor.js +56 -0
  124. package/dist/server/workflow-runner-supervisor.js.map +1 -0
  125. package/dist/state/prune.d.ts +1 -1
  126. package/dist/state/prune.js +17 -10
  127. package/dist/state/prune.js.map +1 -1
  128. package/dist/state/schema.js +2 -2
  129. package/dist/state/workflow-messages.d.ts +1 -1
  130. package/dist/state/workflow-messages.js +1 -1
  131. package/dist/state/workflow-messages.js.map +1 -1
  132. package/dist/viewer/backup.js +1 -1
  133. package/dist/viewer/backup.js.map +1 -1
  134. package/dist/viewer/cli.d.ts +2 -2
  135. package/dist/viewer/cli.js +46 -32
  136. package/dist/viewer/cli.js.map +1 -1
  137. package/dist/viewer/tui.d.ts +1 -1
  138. package/dist/viewer/tui.js +1 -1
  139. package/dist/viewer/tui.js.map +1 -1
  140. package/dist/workflows/command-batch.js +2 -2
  141. package/dist/workflows/engine.js +14 -15
  142. package/dist/workflows/engine.js.map +1 -1
  143. package/dist/workflows/store.d.ts +12 -11
  144. package/dist/workflows/store.js +24 -18
  145. package/dist/workflows/store.js.map +1 -1
  146. package/dist/workflows/types.d.ts +2 -2
  147. package/docs/2026-08-20-durable-workflow-launch-plan.md +12 -12
  148. package/docs/2026-08-25-workflow-follow-ups.md +7 -7
  149. package/docs/2026-08-25-workflow-settings.md +3 -3
  150. package/docs/2026-08-30-out-of-process-workflow-host-plan.md +3 -3
  151. package/docs/2026-09-01-restore-session-delivery-controls-plan.md +5 -5
  152. package/docs/2026-09-01-unified-workflow-client-plan.md +6 -6
  153. package/docs/2026-09-02-installed-live-e2e-plan.md +3 -3
  154. package/docs/2026-09-02-unify-workflow-messages-plan.md +8 -8
  155. package/docs/2026-09-04-workflow-run-state-plan.md +6 -6
  156. package/docs/DEFERRED_TURNS.md +7 -7
  157. package/docs/DESIGN_PHILOSOPHY.md +1 -1
  158. package/docs/HUMAN_DECISIONS.md +11 -11
  159. package/docs/HUMAN_DECISION_PRESENTATIONS.md +4 -4
  160. package/docs/MONITOR.md +1 -1
  161. package/docs/RESOURCE_MANAGERS.md +221 -0
  162. package/docs/SQLITE_STATE.md +35 -33
  163. package/docs/WORKFLOW_COMPOSITION.md +1 -1
  164. package/docs/{WORKFLOW_HOST.md → WORKFLOW_SERVER.md} +125 -119
  165. package/docs/WORKFLOW_STEP_MESSAGES.md +18 -18
  166. package/docs/WORKFLOW_UPDATES.md +16 -16
  167. package/docs/development.md +15 -14
  168. package/docs/live-replay-protocol.md +20 -20
  169. package/docs/plans/2026-08-04-controller-runtime-plan.md +25 -25
  170. package/docs/plans/2026-08-05-always-on-workflows-plan.md +8 -8
  171. package/docs/plans/2026-08-10-agent-managed-monitor-workflows-plan.md +2 -2
  172. package/docs/plans/2026-08-13-session-addressed-workflow-notifications-plan.md +1 -1
  173. package/docs/plans/2026-08-16-workflow-updates-plan.md +5 -5
  174. package/docs/plans/2026-08-19-human-decision-gates-plan.md +1 -1
  175. package/docs/plans/2026-08-20-bounded-command-batches-plan.md +1 -1
  176. package/docs/plans/2026-08-21-deferred-turn-intents-plan.md +3 -3
  177. package/docs/plans/2026-08-21-sanity-check-plan.md +2 -2
  178. package/docs/plans/2026-08-23-assistant-agent-completion-plan.md +5 -5
  179. package/docs/plans/2026-08-23-sqlite-state-plan.md +25 -25
  180. package/docs/plans/2026-08-25-live-workflow-settings-plan.md +4 -4
  181. package/docs/plans/2026-08-27-workflow-terminal-restart-plan.md +3 -3
  182. package/docs/plans/2026-09-04-workflow-runner-resume-state-plan.md +318 -0
  183. package/docs/plans/piw-viewer-experience-implementation-plan.md +1 -1
  184. package/docs/tui-viewer.md +9 -9
  185. package/docs/workflows.md +72 -66
  186. package/examples/{controllers/pull-request.controller.ts → resource-managers/pull-request.resource-manager.ts} +12 -12
  187. package/herdr-plugin.toml +1 -1
  188. package/package.json +12 -11
  189. package/protocol/client.v1.schema.json +7 -7
  190. package/protocol/fixtures/client-v1.json +1 -1
  191. package/src/builtins/monitor.workflow.ts +9 -9
  192. package/src/builtins/pi-agent-group.ts +3 -3
  193. package/src/channels/adapter-entry.ts +14 -14
  194. package/src/client/client.ts +33 -32
  195. package/src/client/protocol.ts +16 -11
  196. package/src/client/resolver.ts +4 -4
  197. package/src/client/view.ts +1 -1
  198. package/src/extension/index.ts +44 -34
  199. package/src/extension/recorder.ts +1 -1
  200. package/src/extension/remote-recorder-store.ts +2 -2
  201. package/src/extension/resource-manager-command.ts +45 -0
  202. package/src/extension/session-delivery.ts +2 -2
  203. package/src/extension/session-view.ts +1 -1
  204. package/src/extension/workflow-message-coordinator.ts +6 -6
  205. package/src/{controllers → resource-managers}/conditions.ts +23 -23
  206. package/src/resource-managers/definition.ts +71 -0
  207. package/src/{controllers → resource-managers}/effects.ts +9 -9
  208. package/src/resource-managers/errors.ts +27 -0
  209. package/src/resource-managers/index.ts +88 -0
  210. package/src/resource-managers/loader.ts +111 -0
  211. package/src/{controllers → resource-managers}/results.ts +4 -4
  212. package/src/{controllers/manager.ts → resource-managers/runtime.ts} +95 -92
  213. package/src/{controllers → resource-managers}/sqlite.ts +198 -186
  214. package/src/{controllers → resource-managers}/store.ts +46 -38
  215. package/src/{controllers → resource-managers}/types.ts +50 -41
  216. package/src/{controllers → resource-managers}/workflows.ts +43 -41
  217. package/src/{host → server}/channel-supervisor.ts +8 -8
  218. package/src/{host/child-worker-supervisor.ts → server/child-runner-supervisor.ts} +22 -18
  219. package/src/{host → server}/processes.ts +3 -3
  220. package/src/{host → server}/resolver-entry.ts +28 -25
  221. package/src/{host/controller-worker-entry.ts → server/resource-runner-entry.ts} +67 -65
  222. package/src/server/resource-runner-protocol.ts +103 -0
  223. package/src/server/resource-runner-supervisor.ts +76 -0
  224. package/src/{host → server}/rpc-bridge.ts +3 -3
  225. package/src/{host → server}/rpc-executor.ts +4 -4
  226. package/src/{host/host-entry.ts → server/server-entry.ts} +5 -5
  227. package/src/{host/runner.ts → server/server.ts} +526 -461
  228. package/src/{host → server}/state.ts +78 -67
  229. package/src/{host → server}/view.ts +15 -15
  230. package/src/server/workflow-runner-content.ts +119 -0
  231. package/src/{host/worker-entry.ts → server/workflow-runner-entry.ts} +98 -57
  232. package/src/server/workflow-runner-protocol.ts +241 -0
  233. package/src/{host/worker-store.ts → server/workflow-runner-store.ts} +18 -20
  234. package/src/server/workflow-runner-supervisor.ts +79 -0
  235. package/src/state/prune.ts +27 -9
  236. package/src/state/schema.ts +2 -2
  237. package/src/state/workflow-messages.ts +1 -1
  238. package/src/viewer/backup.ts +1 -1
  239. package/src/viewer/cli.ts +50 -36
  240. package/src/viewer/tui.ts +1 -1
  241. package/src/workflows/command-batch.ts +2 -2
  242. package/src/workflows/engine.ts +14 -15
  243. package/src/workflows/store.ts +31 -28
  244. package/src/workflows/types.ts +2 -2
  245. package/dist/controllers/conditions.d.ts +0 -6
  246. package/dist/controllers/conditions.js.map +0 -1
  247. package/dist/controllers/definition.d.ts +0 -6
  248. package/dist/controllers/definition.js +0 -45
  249. package/dist/controllers/definition.js.map +0 -1
  250. package/dist/controllers/effects.d.ts +0 -15
  251. package/dist/controllers/effects.js.map +0 -1
  252. package/dist/controllers/errors.d.ts +0 -12
  253. package/dist/controllers/errors.js +0 -25
  254. package/dist/controllers/errors.js.map +0 -1
  255. package/dist/controllers/index.d.ts +0 -12
  256. package/dist/controllers/index.js +0 -12
  257. package/dist/controllers/index.js.map +0 -1
  258. package/dist/controllers/json.js.map +0 -1
  259. package/dist/controllers/loader.d.ts +0 -23
  260. package/dist/controllers/loader.js +0 -74
  261. package/dist/controllers/loader.js.map +0 -1
  262. package/dist/controllers/manager.d.ts +0 -59
  263. package/dist/controllers/manager.js.map +0 -1
  264. package/dist/controllers/results.d.ts +0 -5
  265. package/dist/controllers/results.js.map +0 -1
  266. package/dist/controllers/sqlite.js.map +0 -1
  267. package/dist/controllers/workflows.d.ts +0 -34
  268. package/dist/controllers/workflows.js.map +0 -1
  269. package/dist/extension/controller-command.js.map +0 -1
  270. package/dist/host/channel-effects.js.map +0 -1
  271. package/dist/host/channel-supervisor.js.map +0 -1
  272. package/dist/host/child-worker-supervisor.js.map +0 -1
  273. package/dist/host/controller-worker-entry.d.ts +0 -2
  274. package/dist/host/controller-worker-entry.js.map +0 -1
  275. package/dist/host/controller-worker-protocol.d.ts +0 -36
  276. package/dist/host/controller-worker-protocol.js +0 -49
  277. package/dist/host/controller-worker-protocol.js.map +0 -1
  278. package/dist/host/controller-worker-supervisor.d.ts +0 -21
  279. package/dist/host/controller-worker-supervisor.js +0 -54
  280. package/dist/host/controller-worker-supervisor.js.map +0 -1
  281. package/dist/host/host-entry.js.map +0 -1
  282. package/dist/host/processes.js.map +0 -1
  283. package/dist/host/resolver-entry.js.map +0 -1
  284. package/dist/host/rpc-bridge.js.map +0 -1
  285. package/dist/host/rpc-executor.js.map +0 -1
  286. package/dist/host/runner.js.map +0 -1
  287. package/dist/host/state.js.map +0 -1
  288. package/dist/host/view.js.map +0 -1
  289. package/dist/host/worker-entry.js.map +0 -1
  290. package/dist/host/worker-protocol.d.ts +0 -46
  291. package/dist/host/worker-protocol.js +0 -122
  292. package/dist/host/worker-protocol.js.map +0 -1
  293. package/dist/host/worker-store.js.map +0 -1
  294. package/dist/host/worker-supervisor.d.ts +0 -22
  295. package/dist/host/worker-supervisor.js.map +0 -1
  296. package/docs/CONTROLLERS.md +0 -217
  297. package/src/controllers/definition.ts +0 -65
  298. package/src/controllers/errors.ts +0 -27
  299. package/src/controllers/index.ts +0 -88
  300. package/src/controllers/loader.ts +0 -104
  301. package/src/extension/controller-command.ts +0 -45
  302. package/src/host/controller-worker-protocol.ts +0 -104
  303. package/src/host/controller-worker-supervisor.ts +0 -79
  304. package/src/host/worker-protocol.ts +0 -176
  305. package/src/host/worker-supervisor.ts +0 -74
  306. /package/dist/{controllers → resource-managers}/json.d.ts +0 -0
  307. /package/dist/{controllers → resource-managers}/json.js +0 -0
  308. /package/dist/{controllers → resource-managers}/results.js +0 -0
  309. /package/dist/{controllers → resource-managers}/store.js +0 -0
  310. /package/dist/{controllers → resource-managers}/types.js +0 -0
  311. /package/dist/{host → server}/channel-effects.d.ts +0 -0
  312. /package/dist/{host → server}/channel-effects.js +0 -0
  313. /package/dist/{host/host-entry.d.ts → server/server-entry.d.ts} +0 -0
  314. /package/src/{controllers → resource-managers}/json.ts +0 -0
  315. /package/src/{host → server}/channel-effects.ts +0 -0
@@ -8,12 +8,12 @@ import { initializeViewerRun, recordViewerDeltas } from "../state/viewer.js";
8
8
  import { WorkflowMessageStore } from "../state/workflow-messages.js";
9
9
  import {
10
10
  EffectRequestConflictError,
11
- ResourceConflictError,
12
- ResourceNotFoundError,
11
+ ManagedResourceConflictError,
12
+ ManagedResourceNotFoundError,
13
13
  WorkflowRequestConflictError,
14
14
  } from "./errors.js";
15
15
  import type {
16
- ControllerStore,
16
+ ResourceManagerStore,
17
17
  EffectReservation,
18
18
  QueueItem,
19
19
  QueueRequeueOptions,
@@ -22,11 +22,11 @@ import type {
22
22
  } from "./store.js";
23
23
  import type {
24
24
  ChildWorkflowRecord,
25
- ControllerEvent,
26
- ControllerQueueClaim,
27
- ControllerResource,
28
- ControllerResourceRef,
29
- ControllerResourceStatus,
25
+ ResourceManagerEvent,
26
+ ResourceManagerQueueClaim,
27
+ ManagedResource,
28
+ ManagedResourceRef,
29
+ ManagedResourceStatus,
30
30
  EffectRecord,
31
31
  JsonObject,
32
32
  } from "./types.js";
@@ -139,11 +139,11 @@ export type RunEventRecord = {
139
139
  payload: JsonObject;
140
140
  };
141
141
 
142
- type ControllerRow = {
143
- controllerResourceId: string;
142
+ type ResourceManagerRow = {
143
+ managedResourceId: string;
144
144
  resourceId: string;
145
145
  resourceVersion: number;
146
- controllerName: string;
146
+ resourceManagerName: string;
147
147
  resourceKey: string;
148
148
  uid: string;
149
149
  generation: number;
@@ -268,7 +268,7 @@ type WorkflowRow = {
268
268
  errorHash: Buffer | null;
269
269
  };
270
270
 
271
- export class SqliteControllerStore implements ControllerStore {
271
+ export class SqliteResourceManagerStore implements ResourceManagerStore {
272
272
  readonly filePath: string;
273
273
  readonly state: StateDatabase;
274
274
  private readonly workflowMessages: WorkflowMessageStore;
@@ -282,7 +282,7 @@ export class SqliteControllerStore implements ControllerStore {
282
282
  readOnly?: boolean;
283
283
  projectPath?: string;
284
284
  state?: StateDatabase;
285
- /** Host-only global view. Project-scoped mutations still require projectPath. */
285
+ /** Server-only global view. Project-scoped mutations still require projectPath. */
286
286
  global?: boolean;
287
287
  } = {},
288
288
  ) {
@@ -312,31 +312,34 @@ export class SqliteControllerStore implements ControllerStore {
312
312
  }
313
313
 
314
314
  putResource<TSpec, TStatus>(options: {
315
- controller: string;
315
+ resourceManager: string;
316
316
  key: string;
317
317
  spec: TSpec;
318
318
  initialStatus: TStatus;
319
319
  now?: string;
320
- }): ControllerResource<TSpec, TStatus> {
320
+ }): ManagedResource<TSpec, TStatus> {
321
321
  this.assertWritable();
322
- validateName(options.controller, "controller");
322
+ validateName(options.resourceManager, "resource manager");
323
323
  validateKey(options.key, "resource key");
324
324
  const now = epoch(validTimestamp(options.now));
325
325
  const specHash = this.state.putJson(options.spec, now);
326
- const initialStatus: ControllerResourceStatus<TStatus> = {
326
+ const initialStatus: ManagedResourceStatus<TStatus> = {
327
327
  observedGeneration: 0,
328
328
  conditions: [],
329
- controllerStatus: options.initialStatus,
329
+ resourceManagerStatus: options.initialStatus,
330
330
  };
331
331
  const statusHash = this.state.putJson(initialStatus, now);
332
332
  return this.state.transaction(() => {
333
- const existing = this.controllerRow({ controller: options.controller, key: options.key });
333
+ const existing = this.resourceManagerRow({
334
+ resourceManager: options.resourceManager,
335
+ key: options.key,
336
+ });
334
337
  if (existing === undefined) {
335
338
  const uid = randomUUID();
336
- const controllerResourceId = `controller-resource-${randomUUID()}`;
339
+ const managedResourceId = `controller-resource-${randomUUID()}`;
337
340
  const resourceId = resourceIdFor(
338
341
  "controller",
339
- `${this.requireProjectId()}:${options.controller}:${options.key}`,
342
+ `${this.requireProjectId()}:${options.resourceManager}:${options.key}`,
340
343
  );
341
344
  this.state.connection
342
345
  .prepare(
@@ -344,7 +347,7 @@ export class SqliteControllerStore implements ControllerStore {
344
347
  resource_id, resource_type, aggregate_key, revision, created_at, updated_at
345
348
  ) VALUES (?, 'controller', ?, 1, ?, ?)`,
346
349
  )
347
- .run(resourceId, controllerResourceId, now, now);
350
+ .run(resourceId, managedResourceId, now, now);
348
351
  this.state.connection
349
352
  .prepare("INSERT INTO leases(resource_id, generation) VALUES (?, 0)")
350
353
  .run(resourceId);
@@ -356,10 +359,10 @@ export class SqliteControllerStore implements ControllerStore {
356
359
  ) VALUES (?, ?, ?, ?, ?, ?, 1, ?, ?, ?, ?)`,
357
360
  )
358
361
  .run(
359
- controllerResourceId,
362
+ managedResourceId,
360
363
  resourceId,
361
364
  this.requireProjectId(),
362
- options.controller,
365
+ options.resourceManager,
363
366
  options.key,
364
367
  uid,
365
368
  specHash,
@@ -367,7 +370,7 @@ export class SqliteControllerStore implements ControllerStore {
367
370
  now,
368
371
  now,
369
372
  );
370
- this.enqueueControllerRow(controllerResourceId, now, now);
373
+ this.enqueueResourceManagerRow(managedResourceId, now, now);
371
374
  this.insertEvent(
372
375
  resourceId,
373
376
  1,
@@ -385,9 +388,9 @@ export class SqliteControllerStore implements ControllerStore {
385
388
  SET spec_hash = ?, generation = generation + 1, updated_at = ?
386
389
  WHERE controller_resource_id = ?`,
387
390
  )
388
- .run(specHash, now, existing.controllerResourceId);
391
+ .run(specHash, now, existing.managedResourceId);
389
392
  this.bumpResource(existing.resourceId, existing.resourceVersion, now);
390
- this.enqueueControllerRow(existing.controllerResourceId, now, now);
393
+ this.enqueueResourceManagerRow(existing.managedResourceId, now, now);
391
394
  this.insertEvent(
392
395
  existing.resourceId,
393
396
  revision,
@@ -399,74 +402,74 @@ export class SqliteControllerStore implements ControllerStore {
399
402
  );
400
403
  }
401
404
  return this.requireResource({
402
- controller: options.controller,
405
+ resourceManager: options.resourceManager,
403
406
  key: options.key,
404
- }) as ControllerResource<TSpec, TStatus>;
407
+ }) as ManagedResource<TSpec, TStatus>;
405
408
  });
406
409
  }
407
410
 
408
411
  getResource<TSpec = unknown, TStatus = unknown>(
409
- ref: ControllerResourceRef,
410
- ): ControllerResource<TSpec, TStatus> | undefined {
411
- const row = this.controllerRow(ref);
412
+ ref: ManagedResourceRef,
413
+ ): ManagedResource<TSpec, TStatus> | undefined {
414
+ const row = this.resourceManagerRow(ref);
412
415
  return row === undefined
413
416
  ? undefined
414
- : (this.mapControllerResource(row) as ControllerResource<TSpec, TStatus>);
417
+ : (this.mapManagedResource(row) as ManagedResource<TSpec, TStatus>);
415
418
  }
416
419
 
417
- getResourceByUid(uid: string): ControllerResource | undefined {
418
- const row = this.state.connection.prepare(controllerSelect("WHERE c.uid = ?")).get(uid);
419
- return isControllerRow(row) ? this.mapControllerResource(row) : undefined;
420
+ getResourceByUid(uid: string): ManagedResource | undefined {
421
+ const row = this.state.connection.prepare(resourceManagerSelect("WHERE c.uid = ?")).get(uid);
422
+ return isResourceManagerRow(row) ? this.mapManagedResource(row) : undefined;
420
423
  }
421
424
 
422
425
  listResources<TSpec = unknown, TStatus = unknown>(
423
- options: { controller?: string } = {},
424
- ): ControllerResource<TSpec, TStatus>[] {
426
+ options: { resourceManager?: string } = {},
427
+ ): ManagedResource<TSpec, TStatus>[] {
425
428
  const clauses = ["1 = 1"];
426
429
  const params: unknown[] = [];
427
430
  if (this.projectId !== null) {
428
431
  clauses.push("c.project_id = ?");
429
432
  params.push(this.projectId);
430
433
  }
431
- if (options.controller !== undefined) {
434
+ if (options.resourceManager !== undefined) {
432
435
  clauses.push("c.controller_name = ?");
433
- params.push(options.controller);
436
+ params.push(options.resourceManager);
434
437
  }
435
438
  const rows = this.state.connection
436
439
  .prepare(
437
- controllerSelect(
440
+ resourceManagerSelect(
438
441
  `WHERE ${clauses.join(" AND ")} ORDER BY c.controller_name, c.resource_key`,
439
442
  ),
440
443
  )
441
444
  .all(...params);
442
445
  return rows
443
- .filter(isControllerRow)
444
- .map((row) => this.mapControllerResource(row) as ControllerResource<TSpec, TStatus>);
446
+ .filter(isResourceManagerRow)
447
+ .map((row) => this.mapManagedResource(row) as ManagedResource<TSpec, TStatus>);
445
448
  }
446
449
 
447
450
  updateStatus<TStatus>(options: {
448
- ref: ControllerResourceRef;
451
+ ref: ManagedResourceRef;
449
452
  expectedResourceVersion: number;
450
- claim: ControllerQueueClaim;
451
- status: ControllerResourceStatus<TStatus>;
453
+ claim: ResourceManagerQueueClaim;
454
+ status: ManagedResourceStatus<TStatus>;
452
455
  finalizers?: string[];
453
456
  now?: string;
454
- }): ControllerResource<unknown, TStatus> {
457
+ }): ManagedResource<unknown, TStatus> {
455
458
  const now = epoch(validTimestamp(options.now));
456
459
  return this.state.transaction(() => {
457
- const row = this.requireControllerRow(options.ref);
458
- this.assertControllerClaim(row, options.claim, now);
460
+ const row = this.requireResourceManagerRow(options.ref);
461
+ this.assertResourceManagerClaim(row, options.claim, now);
459
462
  if (row.resourceVersion !== options.expectedResourceVersion) {
460
- throw new ResourceConflictError(options.ref.controller, options.ref.key);
463
+ throw new ManagedResourceConflictError(options.ref.resourceManager, options.ref.key);
461
464
  }
462
465
  const statusHash = this.state.putJson(options.status, now);
463
466
  this.state.connection
464
467
  .prepare(
465
468
  "UPDATE controller_resources SET status_hash = ?, updated_at = ? WHERE controller_resource_id = ?",
466
469
  )
467
- .run(statusHash, now, row.controllerResourceId);
470
+ .run(statusHash, now, row.managedResourceId);
468
471
  if (options.finalizers !== undefined)
469
- this.replaceFinalizers(row.controllerResourceId, options.finalizers);
472
+ this.replaceFinalizers(row.managedResourceId, options.finalizers);
470
473
  this.bumpResource(row.resourceId, row.resourceVersion, now);
471
474
  this.insertEvent(
472
475
  row.resourceId,
@@ -479,22 +482,22 @@ export class SqliteControllerStore implements ControllerStore {
479
482
  options.claim.generation,
480
483
  );
481
484
  options.claim.resourceVersion = row.resourceVersion + 1;
482
- return this.requireResource(options.ref) as ControllerResource<unknown, TStatus>;
485
+ return this.requireResource(options.ref) as ManagedResource<unknown, TStatus>;
483
486
  });
484
487
  }
485
488
 
486
- requestDeletion(ref: ControllerResourceRef, nowValue?: string): ControllerResource {
489
+ requestDeletion(ref: ManagedResourceRef, nowValue?: string): ManagedResource {
487
490
  const now = epoch(validTimestamp(nowValue));
488
491
  return this.state.transaction(() => {
489
- const row = this.requireControllerRow(ref);
492
+ const row = this.requireResourceManagerRow(ref);
490
493
  if (row.deletionRequestedAt === null) {
491
494
  this.state.connection
492
495
  .prepare(
493
496
  "UPDATE controller_resources SET deletion_requested_at = ?, updated_at = ? WHERE controller_resource_id = ?",
494
497
  )
495
- .run(now, now, row.controllerResourceId);
498
+ .run(now, now, row.managedResourceId);
496
499
  this.bumpResource(row.resourceId, row.resourceVersion, now);
497
- this.enqueueControllerRow(row.controllerResourceId, now, now);
500
+ this.enqueueResourceManagerRow(row.managedResourceId, now, now);
498
501
  this.insertEvent(
499
502
  row.resourceId,
500
503
  row.resourceVersion + 1,
@@ -510,21 +513,21 @@ export class SqliteControllerStore implements ControllerStore {
510
513
  }
511
514
 
512
515
  updateFinalizers(options: {
513
- ref: ControllerResourceRef;
516
+ ref: ManagedResourceRef;
514
517
  expectedResourceVersion: number;
515
518
  finalizers: string[];
516
519
  now?: string;
517
- }): ControllerResource {
520
+ }): ManagedResource {
518
521
  const now = epoch(validTimestamp(options.now));
519
522
  return this.state.transaction(() => {
520
- const row = this.requireControllerRow(options.ref);
523
+ const row = this.requireResourceManagerRow(options.ref);
521
524
  if (row.resourceVersion !== options.expectedResourceVersion) {
522
- throw new ResourceConflictError(options.ref.controller, options.ref.key);
525
+ throw new ManagedResourceConflictError(options.ref.resourceManager, options.ref.key);
523
526
  }
524
- this.replaceFinalizers(row.controllerResourceId, options.finalizers);
527
+ this.replaceFinalizers(row.managedResourceId, options.finalizers);
525
528
  this.state.connection
526
529
  .prepare("UPDATE controller_resources SET updated_at = ? WHERE controller_resource_id = ?")
527
- .run(now, row.controllerResourceId);
530
+ .run(now, row.managedResourceId);
528
531
  this.bumpResource(row.resourceId, row.resourceVersion, now);
529
532
  this.insertEvent(
530
533
  row.resourceId,
@@ -540,50 +543,50 @@ export class SqliteControllerStore implements ControllerStore {
540
543
  }
541
544
 
542
545
  deleteResource(
543
- ref: ControllerResourceRef,
546
+ ref: ManagedResourceRef,
544
547
  expectedResourceVersion: number,
545
- claim: ControllerQueueClaim,
548
+ claim: ResourceManagerQueueClaim,
546
549
  ): boolean {
547
550
  return this.state.transaction(() => {
548
- const row = this.requireControllerRow(ref);
549
- this.assertControllerClaim(row, claim, Date.now());
551
+ const row = this.requireResourceManagerRow(ref);
552
+ this.assertResourceManagerClaim(row, claim, Date.now());
550
553
  if (row.resourceVersion !== expectedResourceVersion) {
551
- throw new ResourceConflictError(ref.controller, ref.key);
554
+ throw new ManagedResourceConflictError(ref.resourceManager, ref.key);
552
555
  }
553
- if (row.deletionRequestedAt === null || this.finalizers(row.controllerResourceId).length > 0)
556
+ if (row.deletionRequestedAt === null || this.finalizers(row.managedResourceId).length > 0)
554
557
  return false;
555
558
  this.state.connection
556
559
  .prepare("DELETE FROM controller_resources WHERE controller_resource_id = ?")
557
- .run(row.controllerResourceId);
560
+ .run(row.managedResourceId);
558
561
  return true;
559
562
  });
560
563
  }
561
564
 
562
- enqueue(ref: ControllerResourceRef, availableAt?: string): void {
563
- const row = this.requireControllerRow(ref);
565
+ enqueue(ref: ManagedResourceRef, availableAt?: string): void {
566
+ const row = this.requireResourceManagerRow(ref);
564
567
  const now = Date.now();
565
- this.enqueueControllerRow(row.controllerResourceId, epoch(validTimestamp(availableAt)), now);
568
+ this.enqueueResourceManagerRow(row.managedResourceId, epoch(validTimestamp(availableAt)), now);
566
569
  }
567
570
 
568
571
  claimNext(options: {
569
- controllers: string[];
572
+ resourceManagers: string[];
570
573
  ownerId: string;
571
574
  leaseMs: number;
572
575
  now?: string;
573
- exclude?: ControllerResourceRef[];
574
- }): ControllerQueueClaim | undefined {
575
- if (options.controllers.length === 0) return undefined;
576
+ exclude?: ManagedResourceRef[];
577
+ }): ResourceManagerQueueClaim | undefined {
578
+ if (options.resourceManagers.length === 0) return undefined;
576
579
  const now = epoch(validTimestamp(options.now));
577
- const placeholders = options.controllers.map(() => "?").join(", ");
580
+ const placeholders = options.resourceManagers.map(() => "?").join(", ");
578
581
  const exclusions = options.exclude ?? [];
579
582
  const exclusionSql = exclusions
580
583
  .map(() => "AND NOT (c.controller_name = ? AND c.resource_key = ?)")
581
584
  .join("\n ");
582
- const exclusionParams = exclusions.flatMap((ref) => [ref.controller, ref.key]);
585
+ const exclusionParams = exclusions.flatMap((ref) => [ref.resourceManager, ref.key]);
583
586
  return this.state.transaction(() => {
584
587
  const row = this.state.connection
585
588
  .prepare(
586
- `${controllerSelect(`
589
+ `${resourceManagerSelect(`
587
590
  JOIN controller_queue q ON q.controller_resource_id = c.controller_resource_id
588
591
  JOIN leases l ON l.resource_id = c.resource_id
589
592
  WHERE c.project_id = ?
@@ -594,8 +597,8 @@ export class SqliteControllerStore implements ControllerStore {
594
597
  ORDER BY q.available_at, c.controller_name, c.resource_key
595
598
  LIMIT 1`)}`,
596
599
  )
597
- .get(this.requireProjectId(), ...options.controllers, ...exclusionParams, now, now);
598
- if (!isControllerRow(row)) return undefined;
600
+ .get(this.requireProjectId(), ...options.resourceManagers, ...exclusionParams, now, now);
601
+ if (!isResourceManagerRow(row)) return undefined;
599
602
  const lease = this.requireLease(row.resourceId);
600
603
  const token = randomBytes(32).toString("base64url");
601
604
  const generation = lease.generation + 1;
@@ -633,23 +636,23 @@ export class SqliteControllerStore implements ControllerStore {
633
636
  generation,
634
637
  );
635
638
  return {
636
- controller: row.controllerName,
639
+ resourceManager: row.resourceManagerName,
637
640
  key: row.resourceKey,
638
641
  ownerId: options.ownerId,
639
642
  token,
640
643
  generation,
641
- queueVersion: this.queueVersion(row.controllerResourceId),
644
+ queueVersion: this.queueVersion(row.managedResourceId),
642
645
  resourceVersion: row.resourceVersion + 1,
643
- consecutiveErrors: this.queueErrors(row.controllerResourceId),
646
+ consecutiveErrors: this.queueErrors(row.managedResourceId),
644
647
  expiresAt: new Date(expiresAt).toISOString(),
645
648
  };
646
649
  });
647
650
  }
648
651
 
649
- renewClaim(claim: ControllerQueueClaim, leaseMs: number, nowValue?: string): boolean {
652
+ renewClaim(claim: ResourceManagerQueueClaim, leaseMs: number, nowValue?: string): boolean {
650
653
  const now = epoch(validTimestamp(nowValue));
651
654
  const expiresAt = now + leaseMs;
652
- const row = this.controllerRow({ controller: claim.controller, key: claim.key });
655
+ const row = this.resourceManagerRow({ resourceManager: claim.resourceManager, key: claim.key });
653
656
  if (row === undefined) return false;
654
657
  const result = this.state.connection
655
658
  .prepare(
@@ -670,22 +673,22 @@ export class SqliteControllerStore implements ControllerStore {
670
673
  return result.changes === 1;
671
674
  }
672
675
 
673
- settleClaim(claim: ControllerQueueClaim, nowValue?: string): boolean {
674
- return this.settleControllerClaim(claim, undefined, nowValue);
676
+ settleClaim(claim: ResourceManagerQueueClaim, nowValue?: string): boolean {
677
+ return this.settleResourceManagerClaim(claim, undefined, nowValue);
675
678
  }
676
679
 
677
680
  requeueClaim(
678
- claim: ControllerQueueClaim,
681
+ claim: ResourceManagerQueueClaim,
679
682
  options: QueueRequeueOptions,
680
683
  nowValue?: string,
681
684
  ): boolean {
682
- return this.settleControllerClaim(claim, options, nowValue);
685
+ return this.settleResourceManagerClaim(claim, options, nowValue);
683
686
  }
684
687
 
685
688
  listQueue(): QueueItem[] {
686
689
  const rows = this.state.connection
687
690
  .prepare(
688
- `SELECT c.controller_name AS controller, c.resource_key AS resourceKey,
691
+ `SELECT c.controller_name AS resourceManager, c.resource_key AS resourceKey,
689
692
  q.available_at AS availableAt, q.consecutive_errors AS consecutiveErrors,
690
693
  l.expires_at AS claimExpiresAt
691
694
  FROM controller_queue q
@@ -695,7 +698,7 @@ export class SqliteControllerStore implements ControllerStore {
695
698
  )
696
699
  .all(this.requireProjectId());
697
700
  return rows.filter(isQueueListRow).map((row) => ({
698
- controller: row.controller,
701
+ resourceManager: row.resourceManager,
699
702
  key: row.resourceKey,
700
703
  availableAt: new Date(row.availableAt).toISOString(),
701
704
  consecutiveErrors: row.consecutiveErrors,
@@ -708,7 +711,7 @@ export class SqliteControllerStore implements ControllerStore {
708
711
  reserveEffect(options: {
709
712
  key: string;
710
713
  resourceUid: string;
711
- claim: ControllerQueueClaim;
714
+ claim: ResourceManagerQueueClaim;
712
715
  generation: number;
713
716
  kind: string;
714
717
  requestFingerprint: string;
@@ -716,8 +719,8 @@ export class SqliteControllerStore implements ControllerStore {
716
719
  }): EffectReservation {
717
720
  const now = epoch(validTimestamp(options.now));
718
721
  return this.state.transaction(() => {
719
- const source = this.requireControllerRowByUid(options.resourceUid);
720
- this.assertControllerClaim(source, options.claim, now);
722
+ const source = this.requireResourceManagerRowByUid(options.resourceUid);
723
+ this.assertResourceManagerClaim(source, options.claim, now);
721
724
  const effectId = effectIdFor(source.resourceId, options.key);
722
725
  const existing = this.effectRow(options.resourceUid, options.key);
723
726
  if (existing !== undefined) {
@@ -794,7 +797,7 @@ export class SqliteControllerStore implements ControllerStore {
794
797
  updateEffect(options: {
795
798
  resourceUid: string;
796
799
  key: string;
797
- claim: ControllerQueueClaim;
800
+ claim: ResourceManagerQueueClaim;
798
801
  state: EffectRecord["state"];
799
802
  externalRef?: string;
800
803
  error?: string;
@@ -802,8 +805,8 @@ export class SqliteControllerStore implements ControllerStore {
802
805
  }): EffectRecord {
803
806
  const now = epoch(validTimestamp(options.now));
804
807
  return this.state.transaction(() => {
805
- const source = this.requireControllerRowByUid(options.resourceUid);
806
- this.assertControllerClaim(source, options.claim, now);
808
+ const source = this.requireResourceManagerRowByUid(options.resourceUid);
809
+ this.assertResourceManagerClaim(source, options.claim, now);
807
810
  const row = this.requireEffectRow(options.resourceUid, options.key);
808
811
  const effectResourceId = resourceIdFor("effect", row.effectId);
809
812
  const revision = this.resourceRevision(effectResourceId);
@@ -846,15 +849,15 @@ export class SqliteControllerStore implements ControllerStore {
846
849
 
847
850
  reserveWorkflow(options: {
848
851
  resourceUid: string;
849
- claim: ControllerQueueClaim;
852
+ claim: ResourceManagerQueueClaim;
850
853
  requestKey: string;
851
854
  workflow: string;
852
855
  inputFingerprint: string;
853
856
  }): WorkflowReservation {
854
857
  const now = Date.now();
855
858
  return this.state.transaction(() => {
856
- const source = this.requireControllerRowByUid(options.resourceUid);
857
- this.assertControllerClaim(source, options.claim, now);
859
+ const source = this.requireResourceManagerRowByUid(options.resourceUid);
860
+ this.assertResourceManagerClaim(source, options.claim, now);
858
861
  const existing = this.workflowRow(options.resourceUid, options.requestKey);
859
862
  if (existing !== undefined) {
860
863
  if (
@@ -875,7 +878,7 @@ export class SqliteControllerStore implements ControllerStore {
875
878
  )
876
879
  .run(
877
880
  requestId,
878
- source.controllerResourceId,
881
+ source.managedResourceId,
879
882
  options.requestKey,
880
883
  options.workflow,
881
884
  Buffer.from(options.inputFingerprint, "hex"),
@@ -899,13 +902,13 @@ export class SqliteControllerStore implements ControllerStore {
899
902
  updateWorkflow(
900
903
  requestId: string,
901
904
  update: WorkflowRecordUpdate,
902
- claim: ControllerQueueClaim,
905
+ claim: ResourceManagerQueueClaim,
903
906
  ): ChildWorkflowRecord {
904
907
  const now = Date.now();
905
908
  return this.state.transaction(() => {
906
909
  const row = this.requireWorkflowRow(requestId);
907
- const source = this.requireControllerRowByUid(row.resourceUid);
908
- this.assertControllerClaim(source, claim, now);
910
+ const source = this.requireResourceManagerRowByUid(row.resourceUid);
911
+ this.assertResourceManagerClaim(source, claim, now);
909
912
  const errorHash =
910
913
  update.error === undefined || update.error === null
911
914
  ? null
@@ -945,7 +948,7 @@ export class SqliteControllerStore implements ControllerStore {
945
948
  if (update.runId !== undefined && row.runId !== null && update.runId !== row.runId) {
946
949
  throw new Error("Scheduler completion run ID does not match the reserved child run");
947
950
  }
948
- const source = this.requireControllerRowByUid(row.resourceUid);
951
+ const source = this.requireResourceManagerRowByUid(row.resourceUid);
949
952
  const now = Date.now();
950
953
  return this.state.transaction(() => {
951
954
  const errorHash =
@@ -996,17 +999,20 @@ export class SqliteControllerStore implements ControllerStore {
996
999
  }
997
1000
 
998
1001
  recordEvent(options: {
999
- controller: string;
1002
+ resourceManager: string;
1000
1003
  key: string;
1001
- claim?: ControllerQueueClaim;
1004
+ claim?: ResourceManagerQueueClaim;
1002
1005
  type: string;
1003
1006
  payload?: JsonObject;
1004
1007
  now?: string;
1005
- }): ControllerEvent {
1008
+ }): ResourceManagerEvent {
1006
1009
  const now = epoch(validTimestamp(options.now));
1007
1010
  return this.state.transaction(() => {
1008
- const row = this.requireControllerRow({ controller: options.controller, key: options.key });
1009
- if (options.claim !== undefined) this.assertControllerClaim(row, options.claim, now);
1011
+ const row = this.requireResourceManagerRow({
1012
+ resourceManager: options.resourceManager,
1013
+ key: options.key,
1014
+ });
1015
+ if (options.claim !== undefined) this.assertResourceManagerClaim(row, options.claim, now);
1010
1016
  const revision = this.resourceRevision(row.resourceId) + 1;
1011
1017
  this.bumpResource(row.resourceId, revision - 1, now);
1012
1018
  const eventId = this.insertEvent(
@@ -1024,11 +1030,11 @@ export class SqliteControllerStore implements ControllerStore {
1024
1030
  .prepare("SELECT event_seq AS seq FROM events WHERE event_id = ?")
1025
1031
  .get(eventId);
1026
1032
  /* istanbul ignore if -- exact schema and internal query shape */
1027
- if (!isSequenceRow(event)) throw new Error("Controller event was not recorded");
1033
+ if (!isSequenceRow(event)) throw new Error("ResourceManager event was not recorded");
1028
1034
  return {
1029
1035
  seq: event.seq,
1030
1036
  recordedAt: new Date(now).toISOString(),
1031
- controller: options.controller,
1037
+ resourceManager: options.resourceManager,
1032
1038
  key: options.key,
1033
1039
  type: options.type,
1034
1040
  payload: options.payload ?? {},
@@ -1037,17 +1043,17 @@ export class SqliteControllerStore implements ControllerStore {
1037
1043
  }
1038
1044
 
1039
1045
  listEvents(
1040
- options: { controller?: string; key?: string; limit?: number } = {},
1041
- ): ControllerEvent[] {
1046
+ options: { resourceManager?: string; key?: string; limit?: number } = {},
1047
+ ): ResourceManagerEvent[] {
1042
1048
  const clauses = ["r.resource_type = 'controller'"];
1043
1049
  const params: unknown[] = [];
1044
1050
  if (this.projectId !== null) {
1045
1051
  clauses.push("c.project_id = ?");
1046
1052
  params.push(this.projectId);
1047
1053
  }
1048
- if (options.controller !== undefined) {
1054
+ if (options.resourceManager !== undefined) {
1049
1055
  clauses.push("c.controller_name = ?");
1050
- params.push(options.controller);
1056
+ params.push(options.resourceManager);
1051
1057
  }
1052
1058
  if (options.key !== undefined) {
1053
1059
  clauses.push("c.resource_key = ?");
@@ -1057,7 +1063,7 @@ export class SqliteControllerStore implements ControllerStore {
1057
1063
  const rows = this.state.connection
1058
1064
  .prepare(
1059
1065
  `SELECT e.event_seq AS seq, e.recorded_at AS recordedAt,
1060
- c.controller_name AS controller, c.resource_key AS resourceKey,
1066
+ c.controller_name AS resourceManager, c.resource_key AS resourceKey,
1061
1067
  e.event_type AS eventType, e.payload_hash AS payloadHash
1062
1068
  FROM events e
1063
1069
  JOIN resources r ON r.resource_id = e.resource_id
@@ -1066,10 +1072,10 @@ export class SqliteControllerStore implements ControllerStore {
1066
1072
  ORDER BY e.event_seq DESC LIMIT ?`,
1067
1073
  )
1068
1074
  .all(...params);
1069
- return rows.filter(isControllerEventRow).map((row) => ({
1075
+ return rows.filter(isResourceManagerEventRow).map((row) => ({
1070
1076
  seq: row.seq,
1071
1077
  recordedAt: new Date(row.recordedAt).toISOString(),
1072
- controller: row.controller,
1078
+ resourceManager: row.resourceManager,
1073
1079
  key: row.resourceKey,
1074
1080
  type: row.eventType,
1075
1081
  payload: row.payloadHash === null ? {} : (this.state.readJson(row.payloadHash) as JsonObject),
@@ -1406,7 +1412,7 @@ export class SqliteControllerStore implements ControllerStore {
1406
1412
  return this.claimRun(options.runId, options.runnerId, options.claimToken, options.leaseMs, now);
1407
1413
  }
1408
1414
 
1409
- /** Schedule a worker that validates one pending interactive submission. */
1415
+ /** Schedule a runner that validates one pending interactive submission. */
1410
1416
  claimWorkflowRunForInteractionValidation(options: {
1411
1417
  runId: string;
1412
1418
  runnerId: string;
@@ -1427,7 +1433,7 @@ export class SqliteControllerStore implements ControllerStore {
1427
1433
  );
1428
1434
  }
1429
1435
 
1430
- /** Take a short host claim without scheduling a parked interactive run. */
1436
+ /** Take a short server claim without scheduling a parked interactive run. */
1431
1437
  claimWorkflowRunForControl(options: {
1432
1438
  runId: string;
1433
1439
  runnerId: string;
@@ -1559,7 +1565,7 @@ export class SqliteControllerStore implements ControllerStore {
1559
1565
  "(q.affinity_runner_id IS NULL OR q.affinity_runner_id = ? OR q.status IN ('parked', 'starting', 'running'))",
1560
1566
  "NOT (q.status = 'parked' AND (r.status = 'waiting' OR r.paused = 1))",
1561
1567
  "NOT EXISTS (SELECT 1 FROM interactive_requests i WHERE i.run_id = r.run_id AND i.status = 'pending')",
1562
- "(q.error_code IS NULL OR q.error_code NOT IN ('workflowSourceChanged', 'workerNoProgress'))",
1568
+ "(q.error_code IS NULL OR q.error_code NOT IN ('workflowSourceChanged', 'runnerNoProgress'))",
1563
1569
  ];
1564
1570
  const params: unknown[] = [now, now, options.runnerId, options.runnerId];
1565
1571
  if (this.projectId !== null) {
@@ -1672,7 +1678,7 @@ export class SqliteControllerStore implements ControllerStore {
1672
1678
  return this.releaseRunClaim(options.runId, options.claimToken, "parked", options.now);
1673
1679
  }
1674
1680
 
1675
- parkWorkflowRunForWorkerNoProgress(options: {
1681
+ parkWorkflowRunForRunnerNoProgress(options: {
1676
1682
  runId: string;
1677
1683
  claimToken: string;
1678
1684
  detail: string;
@@ -1702,13 +1708,13 @@ export class SqliteControllerStore implements ControllerStore {
1702
1708
  const queue = this.state.connection
1703
1709
  .prepare(
1704
1710
  `UPDATE run_queue
1705
- SET status = 'parked', error_code = 'workerNoProgress', error_hash = ?,
1711
+ SET status = 'parked', error_code = 'runnerNoProgress', error_hash = ?,
1706
1712
  available_at = ?, updated_at = ?, finished_at = NULL
1707
1713
  WHERE run_id = ? AND status IN ('queued', 'starting', 'running', 'parked')`,
1708
1714
  )
1709
1715
  .run(errorHash, now, now, options.runId);
1710
1716
  if (run.changes !== 1 || queue.changes !== 1) {
1711
- throw new Error(`Workflow run ${options.runId} changed during worker recovery`);
1717
+ throw new Error(`Workflow run ${options.runId} changed during runner recovery`);
1712
1718
  }
1713
1719
  const released = this.state.connection
1714
1720
  .prepare(
@@ -1720,7 +1726,7 @@ export class SqliteControllerStore implements ControllerStore {
1720
1726
  .run(row.resourceId, tokenHash(options.claimToken), lease.generation, now);
1721
1727
  /* istanbul ignore if -- the exact live claim is stable in this transaction */
1722
1728
  if (released.changes !== 1) {
1723
- throw new Error(`Workflow run ${options.runId} claim changed during worker recovery`);
1729
+ throw new Error(`Workflow run ${options.runId} claim changed during runner recovery`);
1724
1730
  }
1725
1731
  const revision = this.resourceRevision(row.resourceId);
1726
1732
  this.bumpResource(row.resourceId, revision, now);
@@ -1730,7 +1736,7 @@ export class SqliteControllerStore implements ControllerStore {
1730
1736
  "run.worker_no_progress",
1731
1737
  lease.ownerType ?? "system",
1732
1738
  lease.ownerId,
1733
- { status: "parked", code: "workerNoProgress" },
1739
+ { status: "parked", code: "runnerNoProgress" },
1734
1740
  now,
1735
1741
  lease.generation || undefined,
1736
1742
  );
@@ -2292,84 +2298,87 @@ export class SqliteControllerStore implements ControllerStore {
2292
2298
 
2293
2299
  private requireProjectId(): string {
2294
2300
  if (this.projectId === null)
2295
- throw new Error("Controller project is not registered in the state database");
2301
+ throw new Error("ResourceManager project is not registered in the state database");
2296
2302
  return this.projectId;
2297
2303
  }
2298
2304
 
2299
- private controllerRow(ref: ControllerResourceRef): ControllerRow | undefined {
2305
+ private resourceManagerRow(ref: ManagedResourceRef): ResourceManagerRow | undefined {
2300
2306
  if (this.projectId === null) return undefined;
2301
2307
  const row = this.state.connection
2302
2308
  .prepare(
2303
- controllerSelect("WHERE c.project_id = ? AND c.controller_name = ? AND c.resource_key = ?"),
2309
+ resourceManagerSelect(
2310
+ "WHERE c.project_id = ? AND c.controller_name = ? AND c.resource_key = ?",
2311
+ ),
2304
2312
  )
2305
- .get(this.projectId, ref.controller, ref.key);
2306
- return isControllerRow(row) ? row : undefined;
2313
+ .get(this.projectId, ref.resourceManager, ref.key);
2314
+ return isResourceManagerRow(row) ? row : undefined;
2307
2315
  }
2308
2316
 
2309
- private requireControllerRow(ref: ControllerResourceRef): ControllerRow {
2310
- const row = this.controllerRow(ref);
2311
- if (row === undefined) throw new ResourceNotFoundError(ref.controller, ref.key);
2317
+ private requireResourceManagerRow(ref: ManagedResourceRef): ResourceManagerRow {
2318
+ const row = this.resourceManagerRow(ref);
2319
+ if (row === undefined) throw new ManagedResourceNotFoundError(ref.resourceManager, ref.key);
2312
2320
  return row;
2313
2321
  }
2314
2322
 
2315
- private requireControllerRowByUid(uid: string): ControllerRow {
2316
- const row = this.state.connection.prepare(controllerSelect("WHERE c.uid = ?")).get(uid);
2323
+ private requireResourceManagerRowByUid(uid: string): ResourceManagerRow {
2324
+ const row = this.state.connection.prepare(resourceManagerSelect("WHERE c.uid = ?")).get(uid);
2317
2325
  /* istanbul ignore if -- impossible after exact schema and transaction checks */
2318
- if (!isControllerRow(row)) throw new Error(`Controller resource not found: ${uid}`);
2326
+ if (!isResourceManagerRow(row)) throw new Error(`Managed resource not found: ${uid}`);
2319
2327
  return row;
2320
2328
  }
2321
2329
 
2322
- private requireResource(ref: ControllerResourceRef): ControllerResource {
2330
+ private requireResource(ref: ManagedResourceRef): ManagedResource {
2323
2331
  const resource = this.getResource(ref);
2324
- if (resource === undefined) throw new ResourceNotFoundError(ref.controller, ref.key);
2332
+ if (resource === undefined)
2333
+ throw new ManagedResourceNotFoundError(ref.resourceManager, ref.key);
2325
2334
  return resource;
2326
2335
  }
2327
2336
 
2328
2337
  /* istanbul ignore next -- pure projection covered by integration tests */
2329
- private mapControllerResource(row: ControllerRow): ControllerResource {
2338
+ private mapManagedResource(row: ResourceManagerRow): ManagedResource {
2330
2339
  const spec = this.state.readJson(row.specHash);
2331
- const status = this.state.readJson(row.statusHash) as ControllerResourceStatus<unknown>;
2340
+ const status = this.state.readJson(row.statusHash) as ManagedResourceStatus<unknown>;
2332
2341
  return {
2333
2342
  metadata: {
2334
2343
  uid: row.uid,
2335
- controller: row.controllerName,
2344
+ resourceManager: row.resourceManagerName,
2336
2345
  key: row.resourceKey,
2337
2346
  resourceVersion: row.resourceVersion,
2338
2347
  generation: row.generation,
2339
2348
  ...(row.deletionRequestedAt === null
2340
2349
  ? {}
2341
2350
  : { deletionTimestamp: new Date(row.deletionRequestedAt).toISOString() }),
2342
- finalizers: this.finalizers(row.controllerResourceId),
2351
+ finalizers: this.finalizers(row.managedResourceId),
2343
2352
  },
2344
2353
  spec,
2345
2354
  status,
2346
2355
  };
2347
2356
  }
2348
2357
 
2349
- private finalizers(controllerResourceId: string): string[] {
2358
+ private finalizers(managedResourceId: string): string[] {
2350
2359
  const rows = this.state.connection
2351
2360
  .prepare(
2352
2361
  "SELECT finalizer FROM controller_finalizers WHERE controller_resource_id = ? ORDER BY position",
2353
2362
  )
2354
- .all(controllerResourceId);
2363
+ .all(managedResourceId);
2355
2364
  return rows.flatMap((row) => (isFinalizerRow(row) ? [row.finalizer] : []));
2356
2365
  }
2357
2366
 
2358
- private replaceFinalizers(controllerResourceId: string, finalizers: string[]): void {
2367
+ private replaceFinalizers(managedResourceId: string, finalizers: string[]): void {
2359
2368
  const unique = [...new Set(finalizers)];
2360
2369
  if (unique.length !== finalizers.length)
2361
- throw new Error("Controller finalizers must be unique");
2370
+ throw new Error("ResourceManager finalizers must be unique");
2362
2371
  this.state.connection
2363
2372
  .prepare("DELETE FROM controller_finalizers WHERE controller_resource_id = ?")
2364
- .run(controllerResourceId);
2373
+ .run(managedResourceId);
2365
2374
  const insert = this.state.connection.prepare(
2366
2375
  "INSERT INTO controller_finalizers(controller_resource_id, finalizer, position) VALUES (?, ?, ?)",
2367
2376
  );
2368
- unique.forEach((finalizer, index) => insert.run(controllerResourceId, finalizer, index));
2377
+ unique.forEach((finalizer, index) => insert.run(managedResourceId, finalizer, index));
2369
2378
  }
2370
2379
 
2371
- private enqueueControllerRow(
2372
- controllerResourceId: string,
2380
+ private enqueueResourceManagerRow(
2381
+ managedResourceId: string,
2373
2382
  availableAt: number,
2374
2383
  now: number,
2375
2384
  ): void {
@@ -2384,50 +2393,53 @@ export class SqliteControllerStore implements ControllerStore {
2384
2393
  queue_version = controller_queue.queue_version + 1,
2385
2394
  updated_at = excluded.updated_at`,
2386
2395
  )
2387
- .run(controllerResourceId, availableAt, now, now);
2396
+ .run(managedResourceId, availableAt, now, now);
2388
2397
  }
2389
2398
 
2390
- private queueErrors(controllerResourceId: string): number {
2399
+ private queueErrors(managedResourceId: string): number {
2391
2400
  const row = this.state.connection
2392
2401
  .prepare(
2393
2402
  "SELECT consecutive_errors AS consecutiveErrors FROM controller_queue WHERE controller_resource_id = ?",
2394
2403
  )
2395
- .get(controllerResourceId);
2404
+ .get(managedResourceId);
2396
2405
  return isErrorCountRow(row) ? row.consecutiveErrors : 0;
2397
2406
  }
2398
2407
 
2399
- private queueVersion(controllerResourceId: string): number {
2408
+ private queueVersion(managedResourceId: string): number {
2400
2409
  const row = this.state.connection
2401
2410
  .prepare(
2402
2411
  "SELECT queue_version AS queueVersion FROM controller_queue WHERE controller_resource_id = ?",
2403
2412
  )
2404
- .get(controllerResourceId);
2413
+ .get(managedResourceId);
2405
2414
  /* istanbul ignore if -- exact schema and internal query shape */
2406
2415
  /* istanbul ignore if -- impossible after exact schema and transaction checks */
2407
- if (!isQueueVersionRow(row)) throw new Error("Controller queue item is missing");
2416
+ if (!isQueueVersionRow(row)) throw new Error("ResourceManager queue item is missing");
2408
2417
  return row.queueVersion;
2409
2418
  }
2410
2419
 
2411
- private settleControllerClaim(
2412
- claim: ControllerQueueClaim,
2420
+ private settleResourceManagerClaim(
2421
+ claim: ResourceManagerQueueClaim,
2413
2422
  requeue: QueueRequeueOptions | undefined,
2414
2423
  nowValue?: string,
2415
2424
  ): boolean {
2416
2425
  const now = epoch(validTimestamp(nowValue));
2417
2426
  return this.state.transaction(() => {
2418
- const row = this.controllerRow({ controller: claim.controller, key: claim.key });
2427
+ const row = this.resourceManagerRow({
2428
+ resourceManager: claim.resourceManager,
2429
+ key: claim.key,
2430
+ });
2419
2431
  if (row === undefined) return false;
2420
2432
  try {
2421
- this.assertControllerClaim(row, claim, now, false);
2433
+ this.assertResourceManagerClaim(row, claim, now, false);
2422
2434
  } catch {
2423
2435
  return false;
2424
2436
  }
2425
- const currentQueueVersion = this.queueVersion(row.controllerResourceId);
2437
+ const currentQueueVersion = this.queueVersion(row.managedResourceId);
2426
2438
  if (requeue === undefined) {
2427
2439
  if (currentQueueVersion === claim.queueVersion) {
2428
2440
  this.state.connection
2429
2441
  .prepare("DELETE FROM controller_queue WHERE controller_resource_id = ?")
2430
- .run(row.controllerResourceId);
2442
+ .run(row.managedResourceId);
2431
2443
  }
2432
2444
  } else {
2433
2445
  const errorHash =
@@ -2439,21 +2451,21 @@ export class SqliteControllerStore implements ControllerStore {
2439
2451
  consecutive_errors = consecutive_errors + 1,
2440
2452
  last_error_hash = ?, updated_at = ? WHERE controller_resource_id = ?`,
2441
2453
  )
2442
- .run(epoch(requeue.availableAt), errorHash, now, row.controllerResourceId);
2454
+ .run(epoch(requeue.availableAt), errorHash, now, row.managedResourceId);
2443
2455
  }
2444
2456
  this.releaseLease(row.resourceId, claim, now);
2445
2457
  return true;
2446
2458
  });
2447
2459
  }
2448
2460
 
2449
- private assertControllerClaim(
2450
- row: ControllerRow,
2451
- claim: ControllerQueueClaim,
2461
+ private assertResourceManagerClaim(
2462
+ row: ResourceManagerRow,
2463
+ claim: ResourceManagerQueueClaim,
2452
2464
  now: number,
2453
2465
  requireUnexpired = true,
2454
2466
  ): void {
2455
- if (row.controllerName !== claim.controller || row.resourceKey !== claim.key)
2456
- throw new Error("Controller claim targets another resource");
2467
+ if (row.resourceManagerName !== claim.resourceManager || row.resourceKey !== claim.key)
2468
+ throw new Error("ResourceManager claim targets another resource");
2457
2469
  const lease = this.requireLease(row.resourceId);
2458
2470
  if (
2459
2471
  lease.ownerType !== "controller" ||
@@ -2463,7 +2475,7 @@ export class SqliteControllerStore implements ControllerStore {
2463
2475
  !lease.tokenHash.equals(tokenHash(claim.token)) ||
2464
2476
  (requireUnexpired && (lease.expiresAt === null || lease.expiresAt <= now))
2465
2477
  ) {
2466
- throw new Error("Controller claim is stale");
2478
+ throw new Error("ResourceManager claim is stale");
2467
2479
  }
2468
2480
  }
2469
2481
 
@@ -2481,8 +2493,8 @@ export class SqliteControllerStore implements ControllerStore {
2481
2493
  return row;
2482
2494
  }
2483
2495
 
2484
- private releaseLease(resourceId: string, claim: ControllerQueueClaim, now: number): void {
2485
- const row = this.controllerRow({ controller: claim.controller, key: claim.key });
2496
+ private releaseLease(resourceId: string, claim: ResourceManagerQueueClaim, now: number): void {
2497
+ const row = this.resourceManagerRow({ resourceManager: claim.resourceManager, key: claim.key });
2486
2498
  if (row === undefined) return;
2487
2499
  const revision = this.resourceRevision(resourceId);
2488
2500
  const result = this.state.connection
@@ -2600,7 +2612,7 @@ export class SqliteControllerStore implements ControllerStore {
2600
2612
  resourceUid: row.resourceUid,
2601
2613
  generation: row.generation,
2602
2614
  kind: row.kind,
2603
- state: controllerEffectState(row.state),
2615
+ state: resourceManagerEffectState(row.state),
2604
2616
  requestFingerprint: row.requestFingerprint,
2605
2617
  startedAt: new Date(row.startedAt).toISOString(),
2606
2618
  ...(row.completedAt === null ? {} : { completedAt: new Date(row.completedAt).toISOString() }),
@@ -3129,14 +3141,14 @@ export class SqliteControllerStore implements ControllerStore {
3129
3141
  }
3130
3142
 
3131
3143
  private assertWritable(): void {
3132
- if (this.state.mode === "read-only") throw new Error("Controller store is read-only");
3144
+ if (this.state.mode === "read-only") throw new Error("ResourceManager store is read-only");
3133
3145
  }
3134
3146
  }
3135
3147
 
3136
- function controllerSelect(clause: string): string {
3137
- return `SELECT c.controller_resource_id AS controllerResourceId,
3148
+ function resourceManagerSelect(clause: string): string {
3149
+ return `SELECT c.controller_resource_id AS managedResourceId,
3138
3150
  c.resource_id AS resourceId, r.revision AS resourceVersion,
3139
- c.controller_name AS controllerName, c.resource_key AS resourceKey,
3151
+ c.controller_name AS resourceManagerName, c.resource_key AS resourceKey,
3140
3152
  c.uid, c.generation, c.spec_hash AS specHash, c.status_hash AS statusHash,
3141
3153
  c.deletion_requested_at AS deletionRequestedAt
3142
3154
  FROM controller_resources c JOIN resources r ON r.resource_id = c.resource_id ${clause}`;
@@ -3205,16 +3217,16 @@ function workflowRunViewSelect(clause: string): string {
3205
3217
  }
3206
3218
 
3207
3219
  type QueueListRow = {
3208
- controller: string;
3220
+ resourceManager: string;
3209
3221
  resourceKey: string;
3210
3222
  availableAt: number;
3211
3223
  consecutiveErrors: number;
3212
3224
  claimExpiresAt: number | null;
3213
3225
  };
3214
- type ControllerEventRow = {
3226
+ type ResourceManagerEventRow = {
3215
3227
  seq: number;
3216
3228
  recordedAt: number;
3217
- controller: string;
3229
+ resourceManager: string;
3218
3230
  resourceKey: string;
3219
3231
  eventType: string;
3220
3232
  payloadHash: Buffer | null;
@@ -3231,7 +3243,7 @@ type RunEventRow = {
3231
3243
  function isRecord(value: unknown): value is Record<string, unknown> {
3232
3244
  return typeof value === "object" && value !== null && !Array.isArray(value);
3233
3245
  }
3234
- function isControllerRow(value: unknown): value is ControllerRow {
3246
+ function isResourceManagerRow(value: unknown): value is ResourceManagerRow {
3235
3247
  return isRecord(value);
3236
3248
  }
3237
3249
  function isLeaseRow(value: unknown): value is LeaseRow {
@@ -3338,7 +3350,7 @@ function isWorkflowRow(value: unknown): value is WorkflowRow {
3338
3350
  function isQueueListRow(value: unknown): value is QueueListRow {
3339
3351
  return isRecord(value);
3340
3352
  }
3341
- function isControllerEventRow(value: unknown): value is ControllerEventRow {
3353
+ function isResourceManagerEventRow(value: unknown): value is ResourceManagerEventRow {
3342
3354
  return isRecord(value);
3343
3355
  }
3344
3356
  function isRunEventRow(value: unknown): value is RunEventRow {
@@ -3518,7 +3530,7 @@ function rowToSource(row: RunSourceIdentityRow): QueuedSource["root"] {
3518
3530
  function effectStatus(value: EffectRecord["state"]): string {
3519
3531
  return value === "indeterminate" ? "ambiguous" : value;
3520
3532
  }
3521
- function controllerEffectState(value: string): EffectRecord["state"] {
3533
+ function resourceManagerEffectState(value: string): EffectRecord["state"] {
3522
3534
  return value === "ambiguous" ? "indeterminate" : (value as EffectRecord["state"]);
3523
3535
  }
3524
3536
  function validTimestamp(value?: string): string {