@memberjunction/task-graph 6.1.0-edge.1 → 6.1.0-edge.3

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 (65) hide show
  1. package/LICENSE +180 -4
  2. package/README.md +214 -0
  3. package/dist/TaskClaimStore.d.ts +387 -4
  4. package/dist/TaskClaimStore.d.ts.map +1 -1
  5. package/dist/TaskClaimStore.js +605 -20
  6. package/dist/TaskClaimStore.js.map +1 -1
  7. package/dist/TaskGraphDispatcher.d.ts +668 -5
  8. package/dist/TaskGraphDispatcher.d.ts.map +1 -1
  9. package/dist/TaskGraphDispatcher.js +2942 -127
  10. package/dist/TaskGraphDispatcher.js.map +1 -1
  11. package/dist/TaskGraphService.d.ts +364 -5
  12. package/dist/TaskGraphService.d.ts.map +1 -1
  13. package/dist/TaskGraphService.js +1039 -43
  14. package/dist/TaskGraphService.js.map +1 -1
  15. package/dist/TaskGraphSubmitterImpl.d.ts.map +1 -1
  16. package/dist/TaskGraphSubmitterImpl.js +5 -0
  17. package/dist/TaskGraphSubmitterImpl.js.map +1 -1
  18. package/dist/TaskLoopExecutor.d.ts +62 -0
  19. package/dist/TaskLoopExecutor.d.ts.map +1 -0
  20. package/dist/TaskLoopExecutor.js +248 -0
  21. package/dist/TaskLoopExecutor.js.map +1 -0
  22. package/dist/WorkflowSpecSync.d.ts +28 -2
  23. package/dist/WorkflowSpecSync.d.ts.map +1 -1
  24. package/dist/WorkflowSpecSync.js +83 -2
  25. package/dist/WorkflowSpecSync.js.map +1 -1
  26. package/dist/condition-gate.d.ts +128 -0
  27. package/dist/condition-gate.d.ts.map +1 -0
  28. package/dist/condition-gate.js +257 -0
  29. package/dist/condition-gate.js.map +1 -0
  30. package/dist/debug-state.d.ts +102 -0
  31. package/dist/debug-state.d.ts.map +1 -0
  32. package/dist/debug-state.js +135 -0
  33. package/dist/debug-state.js.map +1 -0
  34. package/dist/index.d.ts +7 -0
  35. package/dist/index.d.ts.map +1 -1
  36. package/dist/index.js +7 -0
  37. package/dist/index.js.map +1 -1
  38. package/dist/operations/TaskGraphDebugOperations.d.ts +99 -0
  39. package/dist/operations/TaskGraphDebugOperations.d.ts.map +1 -0
  40. package/dist/operations/TaskGraphDebugOperations.js +310 -0
  41. package/dist/operations/TaskGraphDebugOperations.js.map +1 -0
  42. package/dist/operations/TaskGraphOperations.d.ts +20 -2
  43. package/dist/operations/TaskGraphOperations.d.ts.map +1 -1
  44. package/dist/operations/TaskGraphOperations.js +51 -8
  45. package/dist/operations/TaskGraphOperations.js.map +1 -1
  46. package/dist/operations/WorkflowDraftOperation.d.ts +37 -0
  47. package/dist/operations/WorkflowDraftOperation.d.ts.map +1 -0
  48. package/dist/operations/WorkflowDraftOperation.js +141 -0
  49. package/dist/operations/WorkflowDraftOperation.js.map +1 -0
  50. package/dist/settlement-rescue.d.ts +85 -0
  51. package/dist/settlement-rescue.d.ts.map +1 -0
  52. package/dist/settlement-rescue.js +119 -0
  53. package/dist/settlement-rescue.js.map +1 -0
  54. package/dist/task-graph-kick.d.ts +3 -0
  55. package/dist/task-graph-kick.d.ts.map +1 -0
  56. package/dist/task-graph-kick.js +17 -0
  57. package/dist/task-graph-kick.js.map +1 -0
  58. package/dist/task-predicates.d.ts +77 -0
  59. package/dist/task-predicates.d.ts.map +1 -0
  60. package/dist/task-predicates.js +75 -0
  61. package/dist/task-predicates.js.map +1 -0
  62. package/dist/types.d.ts +224 -1
  63. package/dist/types.d.ts.map +1 -1
  64. package/dist/types.js.map +1 -1
  65. package/package.json +12 -8
@@ -16,7 +16,20 @@
16
16
  * @module @memberjunction/task-graph
17
17
  */
18
18
  import { IMetadataProvider, UserInfo } from '@memberjunction/core';
19
- import { type TaskGraphSpec } from '@memberjunction/ai-core-plus';
19
+ import { type MJTaskEntity_ITaskStepConfiguration } from '@memberjunction/core-entities';
20
+ import { type TaskGraphInvocationEnvelope, type TaskGraphSpec, type TaskGraphSpecNode, type ForEachOperation, type WhileOperation } from '@memberjunction/ai-core-plus';
21
+ import { type EdgeOverrideVerdict, type StepTarget, type TaskGraphDebugState } from './debug-state.js';
22
+ /**
23
+ * Normalizes a caller-supplied reinvoke depth to a safe cap seed.
24
+ *
25
+ * The runaway-loop cap is a signed comparison over a persisted-verbatim seed, and the remote Submit
26
+ * operation is the one seam where the seed is caller-supplied rather than computed by the engine —
27
+ * a negative value would BUY hops (`-1000` turns a 5-hop cap into 1005). Clamped rather than
28
+ * refused so a stale client sending zero-adjacent noise keeps working, and no accepted value can
29
+ * ever weaken the cap. Exported pure because a boundary rule that cannot be tested directly is a
30
+ * boundary nobody will notice moving.
31
+ */
32
+ export declare function ClampReinvokeDepth(value: unknown): number | undefined;
20
33
  /** Context a submission carries beyond the graph itself. */
21
34
  export type TaskGraphSubmitContext = {
22
35
  /** Environment the tasks belong to. */
@@ -34,6 +47,16 @@ export type TaskGraphSubmitContext = {
34
47
  * re-invoked by a finished graph carries its parent's depth + 1.
35
48
  */
36
49
  ReinvokeDepth?: number;
50
+ /**
51
+ * The invocation's runtime parameters, for the flow dialect's `data`/`context` roots (R3-3).
52
+ * Persisted on the parent because the instance evaluating a condition is routinely not the
53
+ * process that accepted the graph.
54
+ */
55
+ Invocation?: TaskGraphInvocationEnvelope;
56
+ /** Seed `$.debug` on the parent at insert. See `TaskGraphStartDebug`. */
57
+ Debug?: {
58
+ paused?: boolean;
59
+ };
37
60
  };
38
61
  /**
39
62
  * What the parent Task row remembers about the graph beyond its tasks.
@@ -45,6 +68,16 @@ export type TaskGraphSubmitContext = {
45
68
  export type TaskGraphParentMetadata = {
46
69
  continuation: 'message' | 'reinvoke' | 'none';
47
70
  reinvokeDepth: number;
71
+ /**
72
+ * How a failure propagates in this graph — persisted because the dispatcher that settles a graph
73
+ * is routinely not the process that accepted it, and the spec is gone by then.
74
+ *
75
+ * `'block'` (the default) makes a failed step terminal for its dependents. `'edges'` releases
76
+ * them along their drawn paths, which is what lets a workflow author a RECOVERY route. Compiled
77
+ * flows are `'edges'`; without persisting it, every recovery path a flow author draws is dead
78
+ * machinery — the edges exist and nothing ever follows them.
79
+ */
80
+ failureSemantics?: 'block' | 'edges';
48
81
  submittedByAgentRunID: string | null;
49
82
  /**
50
83
  * Who the graph belongs to.
@@ -64,6 +97,36 @@ export type TaskGraphParentMetadata = {
64
97
  * racing the same completion produce one winner rather than two notifications.
65
98
  */
66
99
  continuationDeliveredAt?: string;
100
+ /**
101
+ * HOW it was delivered — written by the same compare-and-swap that sets the timestamp.
102
+ *
103
+ * `'expired'` means the settlement was found after its delivery window, so the run and its cost
104
+ * were corrected but nothing was announced: posting a week-old "your workflow finished" into a
105
+ * live conversation, or starting a fresh billed turn for it, is worse than staying quiet. The
106
+ * distinction has to survive in the row, or an expired settlement is indistinguishable from a
107
+ * delivered one the moment anybody looks afterwards.
108
+ */
109
+ continuationDeliveredAs?: 'delivered' | 'expired' | 'cancelled';
110
+ /**
111
+ * Set, once and durably, when a step declares the workflow finished before its remaining steps.
112
+ *
113
+ * Read by `loadGraphState` so every instance's claim filter knows the remaining steps are about
114
+ * to be skipped. Without it the decision lives only in the deciding instance's memory, and a
115
+ * concurrent poll — including that same instance's, since task execution is not awaited — can
116
+ * claim and start a step the early finish is in the middle of skipping.
117
+ */
118
+ earlyFinishedAt?: string;
119
+ /**
120
+ * The invocation's `data` and `context`, as the flow dialect's roots of the same names (R3-3).
121
+ *
122
+ * Absent for a graph submitted without them, in which case those roots resolve to the same
123
+ * empty-but-readable value any absent data does — a condition on them reads false rather than
124
+ * throwing, exactly as the walker's would on a missing key.
125
+ */
126
+ invocation?: {
127
+ data?: unknown;
128
+ context?: unknown;
129
+ };
67
130
  };
68
131
  /**
69
132
  * Continuation chains are bounded separately from graph nesting.
@@ -87,6 +150,33 @@ export declare const MAX_REINVOKE_DEPTH = 5;
87
150
  * graph wanted" is still to tell the user their work finished.
88
151
  */
89
152
  export declare function ParseTaskGraphParentMetadata(raw: string | null | undefined): TaskGraphParentMetadata;
153
+ /**
154
+ * The JSON bag `persistParent` writes. Exported so start-paused is testable without a database —
155
+ * Pause-after-submit races the first dispatcher poll, so this bag is the only place `paused: true`
156
+ * is guaranteed to land before anyone claims.
157
+ */
158
+ export declare function BuildTaskGraphParentInputPayload(args: {
159
+ continuation: TaskGraphParentMetadata['continuation'];
160
+ reinvokeDepth: number;
161
+ failureSemantics: NonNullable<TaskGraphParentMetadata['failureSemantics']>;
162
+ submittedByAgentRunID: string | null;
163
+ submittedByUserID: string | null;
164
+ invocation?: {
165
+ data?: unknown;
166
+ context?: unknown;
167
+ } | null;
168
+ startPaused?: boolean;
169
+ }): Record<string, unknown>;
170
+ /** What a cancellation actually managed to do. */
171
+ export type TaskGraphCancelResult = {
172
+ /** False when anything the caller asked to stop is still running. */
173
+ Success: boolean;
174
+ /** True only when every non-terminal task in the graph — and its descendants — is Cancelled. */
175
+ Cancelled: boolean;
176
+ /** Named so the caller can say which parts of the workflow are still going. */
177
+ UncancelledTaskNames: string[];
178
+ ErrorMessage?: string;
179
+ };
90
180
  /** True when a continuation chain has gone as far as it may. */
91
181
  export declare function IsReinvokeCapReached(meta: TaskGraphParentMetadata): boolean;
92
182
  export type TaskGraphSubmitResult = {
@@ -97,7 +187,70 @@ export type TaskGraphSubmitResult = {
97
187
  TaskIDMap?: Map<string, string>;
98
188
  ErrorMessage?: string;
99
189
  };
190
+ /** Name of the task type used for agent-orchestrated graphs. */
191
+ export declare const TASK_TYPE_NAME = "AI Workflow";
192
+ /**
193
+ * Reports the node kinds this dispatcher cannot execute, or `null` when the graph is fully runnable.
194
+ *
195
+ * **Why this is a submit-time check and not a validation rule.** `ValidateTaskGraphSpec` is a pure
196
+ * function over the spec: it answers "is this a well-formed graph?", and its answer has to be the
197
+ * same in a browser, a CLI and a server. "Can it run *here*?" is a different question whose answer
198
+ * changes as runners are added, so it belongs to the runtime that owns the runners.
199
+ *
200
+ * **Why refuse rather than persist-and-stall.** Before this existed, `persistTasks` keyed off which
201
+ * configuration field happened to be populated and fell through to "Human task assigned to the
202
+ * submitter" for everything else — so a loop step silently became an approval request nobody asked
203
+ * for and nothing would ever complete. A graph that hangs forever while *looking* like it is waiting
204
+ * on a person is the most expensive failure available here. Refusing at the door instead names the
205
+ * offending step while the workflow is still the author's to edit.
206
+ */
207
+ /**
208
+ * Projects a spec node onto the `Task.Configuration` bag.
209
+ *
210
+ * Everything the row cannot hold in a column of its own: the kind-specific settings, the payload
211
+ * mappings, and the execution policy. Returning `null` for an empty result keeps `Configuration`
212
+ * NULL rather than `"{}"`, so "this step has no settings" reads the same in the database as it does
213
+ * in the spec.
214
+ *
215
+ * **The mappings are the point.** They are how a step's result reaches the payload, and every
216
+ * branch condition downstream reads the payload — so a step persisted without them produces a
217
+ * workflow whose conditions all evaluate against nothing. Undefined is falsy, so that failure looks
218
+ * exactly like a branch legitimately not being taken.
219
+ */
220
+ export declare function BuildStepConfiguration(node: TaskGraphSpecNode): MJTaskEntity_ITaskStepConfiguration | null;
221
+ /**
222
+ * The loop definition on a node, whichever loop kind it is.
223
+ *
224
+ * ForEach and While differ in how they decide to iterate, not in what they repeat, so everything
225
+ * downstream of that decision — body resolution, name collection, persistence — treats them alike.
226
+ */
227
+ export declare function LoopOperationOf(node: TaskGraphSpecNode): ForEachOperation | WhileOperation | null;
228
+ export declare function FindUnrunnableKinds(spec: TaskGraphSpec): string | null;
229
+ /**
230
+ * Reports human steps assigned to someone other than the submitter, or `null` when there are none.
231
+ *
232
+ * Cross-user assignment needs an authorization model (#3524) — deciding that A may put work in B's
233
+ * inbox is a permissions question, not a graph question. Until it lands, a workflow can only ask the
234
+ * person who started it.
235
+ *
236
+ * **Why refuse rather than reassign.** Persist wrote `task.UserID = submitter` unconditionally, so
237
+ * an authored `assignToUserID` was overwritten in silence. Every layer above accepts the field —
238
+ * the flow compiler reads it into the spec, the validator passes it, the spec type declares it — so
239
+ * silence here is indistinguishable from support: the graph submits, a step appears in the WRONG
240
+ * person's inbox, the named person is never told, and the author has no reason to suspect any of it.
241
+ * Refusing while the graph is still the author's to edit is the only point at which saying so costs
242
+ * nothing.
243
+ */
244
+ export declare function FindCrossUserAssignments(spec: TaskGraphSpec, submitterUserID: string): string | null;
100
245
  export declare class TaskGraphService {
246
+ /**
247
+ * Guarded single-statement writes, shared with the dispatcher.
248
+ *
249
+ * The instance id is descriptive only — this service never CLAIMS anything, it only issues
250
+ * guarded transitions whose predicates are about the row's own status rather than about who
251
+ * holds it.
252
+ */
253
+ private readonly claims;
101
254
  /**
102
255
  * Validates and persists a task graph, returning as soon as it is durable.
103
256
  *
@@ -108,13 +261,57 @@ export declare class TaskGraphService {
108
261
  */
109
262
  Submit(spec: TaskGraphSpec, context: TaskGraphSubmitContext): Promise<TaskGraphSubmitResult>;
110
263
  /**
111
- * Cancels a graph and everything in it that has not already settled.
264
+ * Cancels a graph, everything in it that has not already settled, and everything it started.
112
265
  *
113
266
  * Cancels children first: a parent marked `Cancelled` while children are still `Pending` would
114
267
  * leave the dispatcher free to pick those children up, which is the opposite of what the caller
115
268
  * asked for.
269
+ *
270
+ * **The verdict is the outcome, not the attempt** (R2-9). This returned `true` unconditionally
271
+ * while logging each child that failed to cancel — so one failed save left that child `Pending`,
272
+ * told the caller cancellation had succeeded, and let the dispatcher run the child afterwards.
273
+ * The graph could then settle `Complete` and ANNOUNCE ITS COMPLETION into the conversation of a
274
+ * workflow the user had cancelled. A partial cancel now says so and names what survived; the
275
+ * graph stays active, so retrying is meaningful rather than cosmetic.
116
276
  */
117
- Cancel(parentTaskID: string, context: TaskGraphSubmitContext): Promise<boolean>;
277
+ Cancel(parentTaskID: string, context: TaskGraphSubmitContext): Promise<TaskGraphCancelResult>;
278
+ /**
279
+ * `Cancel`, carrying the recursion state the public entry point does not expose.
280
+ *
281
+ * **The depth cap was dead code** (R3-10): `Cancel` passed a literal 0, and the recursion
282
+ * re-entered through `this.Cancel`, which restarted at 0 — so the check could never fire and
283
+ * the "bounded by the reinvoke depth cap" promise was false. A hand-edited `AgentRunID` cycle
284
+ * recursed to stack overflow mid-cancel.
285
+ *
286
+ * The visited set is cheap armour on top: the cap bounds how DEEP a legitimate chain goes, and
287
+ * a cycle is not deep, it is circular. Arithmetic alone would eventually stop it; a visited set
288
+ * stops it immediately and covers linkage shapes the arithmetic does not anticipate.
289
+ */
290
+ private cancelWithDepth;
291
+ /**
292
+ * Cancels the graphs that this graph's own steps submitted, one level at a time.
293
+ *
294
+ * The linkage is `child task → AgentRunID → the graphs that run submitted`, which is exactly how
295
+ * the continuation chain finds its way back up; walking it downward is the same relation read the
296
+ * other way. Depth-capped by the same constant that caps reinvocation, so a self-referencing
297
+ * workflow cannot make cancellation recurse further than it could have spawned.
298
+ *
299
+ * @returns names of tasks in descendant graphs that could not be cancelled
300
+ */
301
+ private cancelNestedGraphs;
302
+ /**
303
+ * Closes the still-open requests raised for a set of tasks.
304
+ *
305
+ * `Canceled` rather than `Expired`: nobody ran out of time, the ask was withdrawn — and the two
306
+ * mean different things downstream, since the dispatcher treats an expired human step as a
307
+ * FAILURE a give-up edge can route around, which would be a lie about a graph somebody stopped
308
+ * on purpose.
309
+ *
310
+ * Failures here are logged and never propagated: the graph is already cancelled, and refusing to
311
+ * finish that because an inbox row would not close would leave the graph in a worse state than
312
+ * the debris it is trying to avoid.
313
+ */
314
+ private cancelOpenRequests;
118
315
  /**
119
316
  * Returns a failed task to `Pending` so the dispatcher can run it again.
120
317
  *
@@ -122,15 +319,177 @@ export declare class TaskGraphService {
122
319
  * leaving them blocked would make the retry pointless, as the graph still could not progress
123
320
  * past this node.
124
321
  */
125
- Retry(taskID: string, context: TaskGraphSubmitContext): Promise<boolean>;
322
+ Retry(taskID: string, context: TaskGraphSubmitContext, inputPayload?: unknown): Promise<boolean>;
323
+ /**
324
+ * Store for the guarded JSON_MODIFY writes. The instance identity and TTL are claim-protocol
325
+ * concerns this class never exercises — the debug writes are instance-free.
326
+ */
327
+ private readonly debugWrites;
328
+ /** Result shape shared by the control verbs: what happened, and the state that now holds. */
329
+ private controlResult;
330
+ /**
331
+ * Loads a graph parent and proves it IS a workflow graph before any debug write.
332
+ *
333
+ * Read with `BypassCache` for the same reason the dispatcher reads rows that way: the debug bag
334
+ * is written by direct `JSON_MODIFY` statements that fire no cache invalidation, so a cached
335
+ * read here could merge new state over a stale copy and silently resurrect a cleared flag.
336
+ */
337
+ private loadWorkflowParent;
338
+ /**
339
+ * Writes the debug-bag fields a verb OWNS, and reports the state that results.
340
+ *
341
+ * Field-scoped on purpose — see {@link TaskClaimStore.TryWriteDebugFields}. A verb declares the
342
+ * paths it is responsible for; everything else in the bag is left exactly as the database has
343
+ * it, so a concurrent step-consume, breakpoint edit, or override cannot be undone by a verb that
344
+ * was not talking about them.
345
+ *
346
+ * The returned state is this instance's best view (read + the fields just written) and is
347
+ * advisory — the same posture the console takes toward frames.
348
+ */
349
+ private writeDebugFields;
350
+ /**
351
+ * Pauses a graph: nothing new is claimed until it is resumed. In-flight steps finish naturally
352
+ * and their completions land — a pause gates claiming and never touches a live claim, which is
353
+ * why there is no "what happens to the claim" question to answer.
354
+ */
355
+ PauseGraph(parentTaskID: string, context: TaskGraphSubmitContext, pausedByUserID?: string | null): Promise<{
356
+ Success: boolean;
357
+ Debug?: TaskGraphDebugState;
358
+ ErrorMessage?: string;
359
+ }>;
360
+ /** Resumes a paused graph. Breakpoints and edge overrides survive — only the pause clears. */
361
+ ResumeGraph(parentTaskID: string, context: TaskGraphSubmitContext): Promise<{
362
+ Success: boolean;
363
+ Debug?: TaskGraphDebugState;
364
+ ErrorMessage?: string;
365
+ }>;
366
+ /**
367
+ * Arms a one-shot step allowance on a paused graph: `'one'` releases the next eligible task,
368
+ * `'wave'` releases the current frontier, a task ID releases exactly that task. The dispatcher
369
+ * consumes the allowance CAS-style, so two instances stepping the same graph release work once.
370
+ */
371
+ StepGraph(parentTaskID: string, target: StepTarget, context: TaskGraphSubmitContext): Promise<{
372
+ Success: boolean;
373
+ Debug?: TaskGraphDebugState;
374
+ ErrorMessage?: string;
375
+ }>;
376
+ /**
377
+ * Replaces the graph's breakpoint set. Every ID must name a child of this graph — a breakpoint
378
+ * on a task in some other graph would gate nothing and silently lie to the person who set it.
379
+ */
380
+ SetBreakpoints(parentTaskID: string, taskIDs: string[], context: TaskGraphSubmitContext): Promise<{
381
+ Success: boolean;
382
+ Debug?: TaskGraphDebugState;
383
+ ErrorMessage?: string;
384
+ }>;
385
+ /**
386
+ * Overrides one edge's condition verdict — the operator's answer for a path the engine cannot
387
+ * decide (a held graph) or decided wrongly (a broken guard). `'false'` reads as "branch not
388
+ * taken" and cascades skips; `'true'` opens the gate; `null` removes the override.
389
+ */
390
+ SetEdgeOverride(parentTaskID: string, edgeID: string, verdict: EdgeOverrideVerdict | null, context: TaskGraphSubmitContext): Promise<{
391
+ Success: boolean;
392
+ Debug?: TaskGraphDebugState;
393
+ ErrorMessage?: string;
394
+ }>;
395
+ /**
396
+ * Declares a Pending step not-taken. Downstream dependents proceed — `Skipped` satisfies a
397
+ * prerequisite — and any open human request for the step is withdrawn so nobody keeps seeing an
398
+ * ask for work the operator decided against.
399
+ */
400
+ SkipTask(taskID: string, context: TaskGraphSubmitContext): Promise<{
401
+ Success: boolean;
402
+ ErrorMessage?: string;
403
+ }>;
404
+ /**
405
+ * Marks a step Complete with an operator-supplied output.
406
+ *
407
+ * Human steps are refused here on purpose: they already have a first-class completion path
408
+ * (`TaskGraph.CompleteTask`) with the assignee/elevation check, and this verb must not become
409
+ * the door that bypasses it.
410
+ */
411
+ ForceCompleteTask(taskID: string, outputPayload: unknown, context: TaskGraphSubmitContext): Promise<{
412
+ Success: boolean;
413
+ ErrorMessage?: string;
414
+ }>;
415
+ /**
416
+ * Replaces a Pending step's input — the "edit the brief before stepping" move at a breakpoint.
417
+ * Applies to this run only; the step must not have started.
418
+ *
419
+ * **A guarded statement, not load-check-save.** The in-memory `Status === 'Pending'` check plus
420
+ * `task.Save()` is an unconditional full-row UPDATE: a task claimed in the window between the
421
+ * load and the save has its claim columns reverted to the pre-claim snapshot *while its body
422
+ * runs*, and a second instance then claims it again — the step executes twice. See
423
+ * {@link TaskClaimStore.TryUpdateInputPayload}, which makes the check and the write one atomic
424
+ * operation whose rowcount is the answer.
425
+ */
426
+ UpdateTaskInput(taskID: string, inputPayload: unknown, context: TaskGraphSubmitContext): Promise<{
427
+ Success: boolean;
428
+ ErrorMessage?: string;
429
+ }>;
126
430
  /** Maps every referenced agent name to its ID, or reports all unresolvable names at once. */
127
431
  private resolveAgents;
128
- /** Finds or creates the task type used for orchestrated graphs. */
432
+ /**
433
+ * Maps every referenced action name to its ID, or reports all unresolvable names at once.
434
+ *
435
+ * Deliberately a mirror of {@link resolveAgents} rather than a generalization of it: the two
436
+ * read different entities and produce different error prose, and the shared shape is three
437
+ * lines. Collapsing them would trade a readable failure message for a parameterized lookup.
438
+ */
439
+ /**
440
+ * Maps every referenced prompt name to its ID.
441
+ *
442
+ * A prompt is addressed by name in the spec and stored as a foreign key on the row, exactly like
443
+ * agents and actions — a name in JSON cannot be joined, checked, or survive a rename.
444
+ */
445
+ private resolvePrompts;
446
+ private resolveActions;
447
+ /**
448
+ * Finds or creates the task type used for orchestrated graphs — exactly one of it, ever.
449
+ *
450
+ * **This resolves the engine's discriminator, not a label** (R2-7). Round 1 scoped every sweep
451
+ * arm and both payload-writing guards to this type, so a second row sharing the name lets
452
+ * different processes bind different IDs — and a graph stamped with the other one is invisible
453
+ * to the sweep, never claimed, never settled, its submitting run `Paused` forever, with no
454
+ * error anywhere.
455
+ *
456
+ * Race-safe by INSERT-then-reselect rather than by checking harder. Two concurrent first-ever
457
+ * submissions both read "not there" and both insert; the unique index added in this round makes
458
+ * the loser's insert fail, and the loser then re-reads and finds the winner's row. Checking
459
+ * first is what created the window, so the fix cannot be a better check.
460
+ */
129
461
  private ensureTaskType;
462
+ /**
463
+ * The `AI Workflow` task type's ID, resolved deterministically.
464
+ *
465
+ * `ORDER BY` is not decoration: two rows sharing the name come back in whatever order the engine
466
+ * chooses, so an unordered `MaxRows: 1` lets two processes bind different IDs from the same
467
+ * data. The index this round adds makes duplicates impossible going forward; the ordering makes
468
+ * the resolution deterministic on a database that still has some, and the warning makes the
469
+ * situation visible rather than merely survivable.
470
+ */
471
+ private findTaskTypeID;
130
472
  /** Writes the parent task that represents the graph as a whole. */
131
473
  private persistParent;
132
474
  /** Writes each child task, returning the tempId -> real ID mapping edges will need. */
133
475
  private persistChildren;
476
+ /**
477
+ * Reports the node kinds this dispatcher cannot yet execute, or `null` when the graph is
478
+ * entirely runnable.
479
+ *
480
+ * **Why this is a submit-time check and not a validation rule.** `ValidateTaskGraphSpec` is a
481
+ * pure function over the spec: it answers "is this a well-formed graph?", and its answer must be
482
+ * the same in a browser, a CLI and a server. "Can it run *here*?" is a different question whose
483
+ * answer changes as runners are added, so it belongs to the runtime that owns the runners.
484
+ *
485
+ * **Why refuse rather than persist-and-stall.** `Prompt`, `ForEach`, `While` and `External`
486
+ * are legitimate parts of the spec, but the `Task` row has nowhere to carry a node's `kind` or
487
+ * its typed `configuration` — so a persisted one could not be dispatched even if a runner
488
+ * existed. Refusing at the door tells the author which step is the problem while the graph is
489
+ * still theirs to edit. The alternative is a graph that submits successfully and then never
490
+ * finishes, which costs an operator an afternoon to diagnose.
491
+ */
492
+ private findUnrunnableKinds;
134
493
  /** Writes the dependency edges, translating tempIds to persisted IDs. */
135
494
  private persistDependencies;
136
495
  private loadChildren;
@@ -1 +1 @@
1
- {"version":3,"file":"TaskGraphService.d.ts","sourceRoot":"","sources":["../src/TaskGraphService.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,EACH,iBAAiB,EAIjB,QAAQ,EACX,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAIH,KAAK,aAAa,EACrB,MAAM,8BAA8B,CAAC;AAEtC,4DAA4D;AAC5D,MAAM,MAAM,sBAAsB,GAAG;IACjC,uCAAuC;IACvC,aAAa,EAAE,MAAM,CAAC;IACtB,qFAAqF;IACrF,oBAAoB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,kDAAkD;IAClD,WAAW,EAAE,QAAQ,CAAC;IACtB,mCAAmC;IACnC,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,oFAAoF;IACpF,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,MAAM,uBAAuB,GAAG;IAClC,YAAY,EAAE,SAAS,GAAG,UAAU,GAAG,MAAM,CAAC;IAC9C,aAAa,EAAE,MAAM,CAAC;IACtB,qBAAqB,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC;;;;;;;;;OASG;IACH,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC;;;;;OAKG;IACH,uBAAuB,CAAC,EAAE,MAAM,CAAC;CACpC,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,kBAAkB,IAAI,CAAC;AAUpC;;;;;;;;;;GAUG;AACH,wBAAgB,4BAA4B,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,uBAAuB,CAmBpG;AAED,gEAAgE;AAChE,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,uBAAuB,GAAG,OAAO,CAE3E;AAED,MAAM,MAAM,qBAAqB,GAAG;IAChC,OAAO,EAAE,OAAO,CAAC;IACjB,8FAA8F;IAC9F,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,0FAA0F;IAC1F,SAAS,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,YAAY,CAAC,EAAE,MAAM,CAAC;CACzB,CAAC;AAKF,qBAAa,gBAAgB;IACzB;;;;;;;OAOG;IACU,MAAM,CAAC,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,qBAAqB,CAAC;IAuCzG;;;;;;OAMG;IACU,MAAM,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,OAAO,CAAC;IAuB5F;;;;;;OAMG;IACU,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,OAAO,CAAC;IAsCrF,6FAA6F;YAC/E,aAAa;IA0B3B,mEAAmE;YACrD,cAAc;IAkB5B,mEAAmE;YACrD,aAAa;IA0B3B,uFAAuF;YACzE,eAAe;IAuC7B,yEAAyE;YAC3D,mBAAmB;YA8BnB,YAAY;CAO7B"}
1
+ {"version":3,"file":"TaskGraphService.d.ts","sourceRoot":"","sources":["../src/TaskGraphService.ts"],"names":[],"mappings":"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"}