@osolmaz/pi-workflows 0.2.0 → 0.4.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 (152) hide show
  1. package/README.md +72 -5
  2. package/dist/builtins/catalog.d.ts +2 -0
  3. package/dist/builtins/catalog.js +22 -0
  4. package/dist/builtins/catalog.js.map +1 -0
  5. package/dist/builtins/monitor.workflow.d.ts +71 -0
  6. package/dist/builtins/monitor.workflow.js +250 -0
  7. package/dist/builtins/monitor.workflow.js.map +1 -0
  8. package/dist/controllers/conditions.d.ts +6 -0
  9. package/dist/controllers/conditions.js +68 -0
  10. package/dist/controllers/conditions.js.map +1 -0
  11. package/dist/controllers/definition.d.ts +6 -0
  12. package/dist/controllers/definition.js +45 -0
  13. package/dist/controllers/definition.js.map +1 -0
  14. package/dist/controllers/effects.d.ts +14 -0
  15. package/dist/controllers/effects.js +104 -0
  16. package/dist/controllers/effects.js.map +1 -0
  17. package/dist/controllers/errors.d.ts +12 -0
  18. package/dist/controllers/errors.js +25 -0
  19. package/dist/controllers/errors.js.map +1 -0
  20. package/dist/controllers/index.d.ts +13 -0
  21. package/dist/controllers/index.js +13 -0
  22. package/dist/controllers/index.js.map +1 -0
  23. package/dist/controllers/json.d.ts +5 -0
  24. package/dist/controllers/json.js +57 -0
  25. package/dist/controllers/json.js.map +1 -0
  26. package/dist/controllers/loader.d.ts +23 -0
  27. package/dist/controllers/loader.js +74 -0
  28. package/dist/controllers/loader.js.map +1 -0
  29. package/dist/controllers/manager.d.ts +58 -0
  30. package/dist/controllers/manager.js +399 -0
  31. package/dist/controllers/manager.js.map +1 -0
  32. package/dist/controllers/results.d.ts +5 -0
  33. package/dist/controllers/results.js +32 -0
  34. package/dist/controllers/results.js.map +1 -0
  35. package/dist/controllers/sqlite.d.ts +235 -0
  36. package/dist/controllers/sqlite.js +1087 -0
  37. package/dist/controllers/sqlite.js.map +1 -0
  38. package/dist/controllers/store.d.ts +112 -0
  39. package/dist/controllers/store.js +32 -0
  40. package/dist/controllers/store.js.map +1 -0
  41. package/dist/controllers/types.d.ts +159 -0
  42. package/dist/controllers/types.js +2 -0
  43. package/dist/controllers/types.js.map +1 -0
  44. package/dist/controllers/workflow-engine-scheduler.d.ts +25 -0
  45. package/dist/controllers/workflow-engine-scheduler.js +95 -0
  46. package/dist/controllers/workflow-engine-scheduler.js.map +1 -0
  47. package/dist/controllers/workflows.d.ts +27 -0
  48. package/dist/controllers/workflows.js +109 -0
  49. package/dist/controllers/workflows.js.map +1 -0
  50. package/dist/extension/controller-host.d.ts +47 -0
  51. package/dist/extension/controller-host.js +110 -0
  52. package/dist/extension/controller-host.js.map +1 -0
  53. package/dist/extension/executor.d.ts +3 -0
  54. package/dist/extension/executor.js +12 -2
  55. package/dist/extension/executor.js.map +1 -1
  56. package/dist/extension/index.d.ts +7 -0
  57. package/dist/extension/index.js +1118 -106
  58. package/dist/extension/index.js.map +1 -1
  59. package/dist/extension/recorder.d.ts +6 -0
  60. package/dist/extension/recorder.js +20 -8
  61. package/dist/extension/recorder.js.map +1 -1
  62. package/dist/extension/workflow-tool.d.ts +28 -0
  63. package/dist/extension/workflow-tool.js +33 -0
  64. package/dist/extension/workflow-tool.js.map +1 -0
  65. package/dist/host/processes.d.ts +24 -0
  66. package/dist/host/processes.js +114 -0
  67. package/dist/host/processes.js.map +1 -0
  68. package/dist/host/rpc-bridge.d.ts +9 -0
  69. package/dist/host/rpc-bridge.js +39 -0
  70. package/dist/host/rpc-bridge.js.map +1 -0
  71. package/dist/host/rpc-executor.d.ts +38 -0
  72. package/dist/host/rpc-executor.js +254 -0
  73. package/dist/host/rpc-executor.js.map +1 -0
  74. package/dist/host/runner.d.ts +50 -0
  75. package/dist/host/runner.js +379 -0
  76. package/dist/host/runner.js.map +1 -0
  77. package/dist/viewer/cli.d.ts +7 -3
  78. package/dist/viewer/cli.js +150 -19
  79. package/dist/viewer/cli.js.map +1 -1
  80. package/dist/workflows/catalog.d.ts +43 -0
  81. package/dist/workflows/catalog.js +79 -0
  82. package/dist/workflows/catalog.js.map +1 -0
  83. package/dist/workflows/engine.d.ts +37 -2
  84. package/dist/workflows/engine.js +297 -29
  85. package/dist/workflows/engine.js.map +1 -1
  86. package/dist/workflows/errors.d.ts +23 -0
  87. package/dist/workflows/errors.js +38 -0
  88. package/dist/workflows/errors.js.map +1 -1
  89. package/dist/workflows/graph.js +0 -5
  90. package/dist/workflows/graph.js.map +1 -1
  91. package/dist/workflows/index.d.ts +2 -2
  92. package/dist/workflows/index.js +1 -1
  93. package/dist/workflows/index.js.map +1 -1
  94. package/dist/workflows/loader.d.ts +19 -15
  95. package/dist/workflows/loader.js +63 -19
  96. package/dist/workflows/loader.js.map +1 -1
  97. package/dist/workflows/migrate-sources.d.ts +41 -0
  98. package/dist/workflows/migrate-sources.js +129 -0
  99. package/dist/workflows/migrate-sources.js.map +1 -0
  100. package/dist/workflows/schema.js +3 -2
  101. package/dist/workflows/schema.js.map +1 -1
  102. package/dist/workflows/store.d.ts +50 -6
  103. package/dist/workflows/store.js +448 -53
  104. package/dist/workflows/store.js.map +1 -1
  105. package/dist/workflows/types.d.ts +27 -3
  106. package/docs/CONTROLLERS.md +215 -0
  107. package/docs/development.md +14 -9
  108. package/docs/plans/2026-08-04-controller-runtime-plan.md +169 -0
  109. package/docs/plans/2026-08-05-always-on-workflows-plan.md +125 -0
  110. package/docs/plans/2026-08-10-agent-managed-monitor-workflows-plan.md +184 -0
  111. package/docs/plans/2026-08-12-coordinated-workflow-timeouts-plan.md +74 -0
  112. package/docs/plans/2026-08-13-built-in-workflow-catalog-plan.md +97 -0
  113. package/docs/run-bundles.md +85 -28
  114. package/docs/workflows.md +161 -17
  115. package/examples/controllers/pull-request.controller.ts +215 -0
  116. package/package.json +10 -2
  117. package/src/builtins/catalog.ts +22 -0
  118. package/src/builtins/monitor.workflow.ts +302 -0
  119. package/src/controllers/conditions.ts +110 -0
  120. package/src/controllers/definition.ts +65 -0
  121. package/src/controllers/effects.ts +123 -0
  122. package/src/controllers/errors.ts +27 -0
  123. package/src/controllers/index.ts +90 -0
  124. package/src/controllers/json.ts +62 -0
  125. package/src/controllers/loader.ts +104 -0
  126. package/src/controllers/manager.ts +533 -0
  127. package/src/controllers/results.ts +46 -0
  128. package/src/controllers/sqlite.ts +1545 -0
  129. package/src/controllers/store.ts +160 -0
  130. package/src/controllers/types.ts +183 -0
  131. package/src/controllers/workflow-engine-scheduler.ts +148 -0
  132. package/src/controllers/workflows.ts +152 -0
  133. package/src/extension/controller-host.ts +163 -0
  134. package/src/extension/executor.ts +13 -2
  135. package/src/extension/index.ts +1325 -130
  136. package/src/extension/recorder.ts +65 -36
  137. package/src/extension/workflow-tool.ts +59 -0
  138. package/src/host/processes.ts +119 -0
  139. package/src/host/rpc-bridge.ts +44 -0
  140. package/src/host/rpc-executor.ts +299 -0
  141. package/src/host/runner.ts +445 -0
  142. package/src/viewer/cli.ts +167 -21
  143. package/src/workflows/catalog.ts +135 -0
  144. package/src/workflows/engine.ts +404 -41
  145. package/src/workflows/errors.ts +45 -0
  146. package/src/workflows/graph.ts +0 -5
  147. package/src/workflows/index.ts +2 -0
  148. package/src/workflows/loader.ts +76 -22
  149. package/src/workflows/migrate-sources.ts +167 -0
  150. package/src/workflows/schema.ts +3 -2
  151. package/src/workflows/store.ts +557 -48
  152. package/src/workflows/types.ts +22 -3
@@ -0,0 +1,235 @@
1
+ import { type ControllerStore, type EffectReservation, type QueueItem, type QueueRequeueOptions, type WorkflowRecordUpdate, type WorkflowReservation } from "./store.js";
2
+ import type { ChildWorkflowRecord, ControllerEvent, ControllerQueueClaim, ControllerResource, ControllerResourceRef, ControllerResourceStatus, EffectRecord, JsonObject } from "./types.js";
3
+ /** A user-started workflow run tracked by the durable run queue. */
4
+ export type WorkflowRunQueueRecord = {
5
+ runId: string;
6
+ /** Human-readable workflow name used in status and event output. */
7
+ workflowName: string;
8
+ /** Canonical source reference used to reopen the run. */
9
+ workflowSourceRef: string;
10
+ input: unknown;
11
+ status: "claimed" | "parked" | "done";
12
+ runnerId: string | null;
13
+ claimToken: string | null;
14
+ claimExpiresAt: string | null;
15
+ affinityRunnerId: string | null;
16
+ parentRunId: string | null;
17
+ createdAt: string;
18
+ updatedAt: string;
19
+ };
20
+ /** One run lifecycle transition in the cross-session event feed. */
21
+ export type RunEventRecord = {
22
+ seq: number;
23
+ recordedAt: string;
24
+ runId: string;
25
+ workflowRef: string;
26
+ type: string;
27
+ runnerId: string | null;
28
+ payload: JsonObject;
29
+ };
30
+ export declare class SqliteControllerStore implements ControllerStore {
31
+ readonly filePath: string;
32
+ private readonly database;
33
+ private closed;
34
+ constructor(filePath?: string, options?: {
35
+ readOnly?: boolean;
36
+ });
37
+ close(): void;
38
+ putResource<TSpec, TStatus>(options: {
39
+ controller: string;
40
+ key: string;
41
+ spec: TSpec;
42
+ initialStatus: TStatus;
43
+ now?: string;
44
+ }): ControllerResource<TSpec, TStatus>;
45
+ getResource<TSpec = unknown, TStatus = unknown>(ref: ControllerResourceRef): ControllerResource<TSpec, TStatus> | undefined;
46
+ getResourceByUid(uid: string): ControllerResource | undefined;
47
+ listResources<TSpec = unknown, TStatus = unknown>(options?: {
48
+ controller?: string;
49
+ }): ControllerResource<TSpec, TStatus>[];
50
+ updateStatus<TStatus>(options: {
51
+ ref: ControllerResourceRef;
52
+ expectedResourceVersion: number;
53
+ status: ControllerResourceStatus<TStatus>;
54
+ finalizers?: string[];
55
+ now?: string;
56
+ }): ControllerResource<unknown, TStatus>;
57
+ requestDeletion(ref: ControllerResourceRef, now?: string): ControllerResource;
58
+ updateFinalizers(options: {
59
+ ref: ControllerResourceRef;
60
+ expectedResourceVersion: number;
61
+ finalizers: string[];
62
+ now?: string;
63
+ }): ControllerResource;
64
+ deleteResource(ref: ControllerResourceRef, expectedResourceVersion: number): boolean;
65
+ enqueue(ref: ControllerResourceRef, availableAt?: string): void;
66
+ claimNext(options: {
67
+ controllers: string[];
68
+ leaseMs: number;
69
+ now?: string;
70
+ }): ControllerQueueClaim | undefined;
71
+ renewClaim(claim: ControllerQueueClaim, leaseMs: number, now?: string): boolean;
72
+ settleClaim(claim: ControllerQueueClaim, now?: string): boolean;
73
+ requeueClaim(claim: ControllerQueueClaim, options: QueueRequeueOptions, _now?: string): boolean;
74
+ listQueue(): QueueItem[];
75
+ reserveEffect(options: {
76
+ key: string;
77
+ resourceUid: string;
78
+ generation: number;
79
+ kind: string;
80
+ requestFingerprint: string;
81
+ now?: string;
82
+ }): EffectReservation;
83
+ getEffect(resourceUid: string, key: string): EffectRecord | undefined;
84
+ updateEffect(options: {
85
+ resourceUid: string;
86
+ key: string;
87
+ state: EffectRecord["state"];
88
+ externalRef?: string;
89
+ error?: string;
90
+ now?: string;
91
+ }): EffectRecord;
92
+ listEffects(resourceUid: string): EffectRecord[];
93
+ reserveWorkflow(options: {
94
+ resourceUid: string;
95
+ requestKey: string;
96
+ workflow: string;
97
+ inputFingerprint: string;
98
+ }): WorkflowReservation;
99
+ getWorkflow(resourceUid: string, requestKey: string): ChildWorkflowRecord | undefined;
100
+ getWorkflowByRequestId(requestId: string): ChildWorkflowRecord | undefined;
101
+ updateWorkflow(requestId: string, update: WorkflowRecordUpdate): ChildWorkflowRecord;
102
+ listWorkflows(resourceUid: string): ChildWorkflowRecord[];
103
+ recordEvent(options: {
104
+ controller: string;
105
+ key: string;
106
+ type: string;
107
+ payload?: JsonObject;
108
+ now?: string;
109
+ }): ControllerEvent;
110
+ listEvents(options?: {
111
+ controller?: string;
112
+ key?: string;
113
+ limit?: number;
114
+ }): ControllerEvent[];
115
+ private configure;
116
+ private initializeSchema;
117
+ private transaction;
118
+ private resourceRow;
119
+ private requireResource;
120
+ private throwMissingOrConflict;
121
+ private enqueueRow;
122
+ private claimedRow;
123
+ private effectRow;
124
+ private requireEffect;
125
+ private workflowRow;
126
+ private requireWorkflow;
127
+ /**
128
+ * Insert a user-started run and claim it in one statement, so the
129
+ * originating runner owns the run from birth (origin affinity).
130
+ */
131
+ enqueueWorkflowRun(options: {
132
+ runId: string;
133
+ workflowName: string;
134
+ workflowSourceRef: string;
135
+ input: unknown;
136
+ runnerId: string;
137
+ claimToken: string;
138
+ leaseMs: number;
139
+ affinityRunnerId?: string;
140
+ parentRunId?: string;
141
+ now?: string;
142
+ }): WorkflowRunQueueRecord;
143
+ getWorkflowRun(runId: string): WorkflowRunQueueRecord | undefined;
144
+ listWorkflowRuns(options?: {
145
+ status?: WorkflowRunQueueRecord["status"];
146
+ }): WorkflowRunQueueRecord[];
147
+ /**
148
+ * Claim the oldest claimable run, preferring runs with affinity to this
149
+ * runner. Parked rows are claimable immediately; claimed rows become
150
+ * claimable once their lease expires, so a dead or stalled runner never
151
+ * strands a run. Returns undefined when nothing is claimable.
152
+ */
153
+ claimNextWorkflowRun(options: {
154
+ runnerId: string;
155
+ claimToken: string;
156
+ leaseMs: number;
157
+ excludeRunIds?: string[];
158
+ now?: string;
159
+ }): WorkflowRunQueueRecord | undefined;
160
+ /** Extend a live claim. Rejects expired or foreign claims. */
161
+ renewWorkflowRunClaim(options: {
162
+ runId: string;
163
+ claimToken: string;
164
+ leaseMs: number;
165
+ now?: string;
166
+ }): boolean;
167
+ /** The fence check: true only while this exact claim is live. */
168
+ verifyWorkflowRunClaim(options: {
169
+ runId: string;
170
+ claimToken: string;
171
+ now?: string;
172
+ }): boolean;
173
+ /** Release a claim and park the run so another runner can resume it. */
174
+ parkWorkflowRun(options: {
175
+ runId: string;
176
+ claimToken: string;
177
+ now?: string;
178
+ }): boolean;
179
+ /**
180
+ * Delete a claimed row. Used when a continuation fails before its bundle
181
+ * exists, so the parent's one-continuation slot is not consumed by a run
182
+ * that never happened.
183
+ */
184
+ deleteWorkflowRun(options: {
185
+ runId: string;
186
+ claimToken: string;
187
+ }): boolean;
188
+ /** Release a claim and mark the run terminal in the queue. */
189
+ completeWorkflowRun(options: {
190
+ runId: string;
191
+ claimToken: string;
192
+ now?: string;
193
+ }): boolean;
194
+ /** Repair a canonical bundle's queue source and claim it only when needed. */
195
+ repairCanonicalWorkflowSourceRun(options: {
196
+ runId: string;
197
+ workflowName: string;
198
+ workflowSourceRef: string;
199
+ runnerId: string;
200
+ claimToken: string;
201
+ leaseMs: number;
202
+ now?: string;
203
+ }): "unchanged" | "claimed" | false;
204
+ /** Claim and rewrite one proved legacy workflow source queue row atomically. */
205
+ claimLegacyWorkflowSourceRun(options: {
206
+ runId: string;
207
+ workflowName: string;
208
+ oldWorkflowPath: string;
209
+ workflowSourceRef: string;
210
+ runnerId: string;
211
+ claimToken: string;
212
+ leaseMs: number;
213
+ now?: string;
214
+ }): boolean;
215
+ /** Append a run lifecycle transition to the event feed. */
216
+ recordRunEvent(options: {
217
+ runId: string;
218
+ workflowRef: string;
219
+ type: string;
220
+ runnerId?: string;
221
+ payload?: JsonObject;
222
+ now?: string;
223
+ }): number;
224
+ /** List run events after a watermark, oldest first. */
225
+ listRunEventsAfter(seq: number, options?: {
226
+ limit?: number;
227
+ }): RunEventRecord[];
228
+ /** The highest run event seq in the feed; 0 when empty. */
229
+ latestRunEventSeq(): number;
230
+ /** The last run event this session was told about; 0 before any sync. */
231
+ getSessionWatermark(sessionId: string): number;
232
+ setSessionWatermark(sessionId: string, seq: number, now?: string): void;
233
+ private requireWorkflowRun;
234
+ private requireEvent;
235
+ }