@orkestrel/workflow 0.0.7 → 0.0.9
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.
- package/README.md +23 -30
- package/dist/src/browser/index.d.ts +23 -38
- package/dist/src/browser/index.js +51 -122
- package/dist/src/browser/index.js.map +1 -1
- package/dist/src/core/index.cjs +1761 -459
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +686 -277
- package/dist/src/core/index.d.ts +686 -277
- package/dist/src/core/index.js +1744 -461
- package/dist/src/core/index.js.map +1 -1
- package/dist/src/server/index.cjs +21 -43
- package/dist/src/server/index.cjs.map +1 -1
- package/dist/src/server/index.d.cts +12 -17
- package/dist/src/server/index.d.ts +12 -17
- package/dist/src/server/index.js +21 -43
- package/dist/src/server/index.js.map +1 -1
- package/package.json +9 -9
|
@@ -7,6 +7,8 @@ import { EmitterErrorHandler } from '@orkestrel/emitter';
|
|
|
7
7
|
import { EmitterHooks } from '@orkestrel/emitter';
|
|
8
8
|
import { EmitterInterface } from '@orkestrel/emitter';
|
|
9
9
|
import { Failure } from '@orkestrel/contract';
|
|
10
|
+
import { JSONRecord } from '@orkestrel/contract';
|
|
11
|
+
import { JSONValue } from '@orkestrel/contract';
|
|
10
12
|
import { LiteralShape } from '@orkestrel/contract';
|
|
11
13
|
import { NumberShape } from '@orkestrel/contract';
|
|
12
14
|
import { ObjectShape } from '@orkestrel/contract';
|
|
@@ -37,7 +39,7 @@ import { TokenUsage } from '@orkestrel/budget';
|
|
|
37
39
|
*
|
|
38
40
|
* @param snapshot - The snapshot to validate
|
|
39
41
|
*/
|
|
40
|
-
export declare function assertSnapshot(snapshot:
|
|
42
|
+
export declare function assertSnapshot(snapshot: unknown): void;
|
|
41
43
|
|
|
42
44
|
/**
|
|
43
45
|
* Build a {@link PhaseContext} — a phase's own identity plus a back-reference to its
|
|
@@ -90,6 +92,54 @@ export declare function buildWorkflowContext(node: WorkflowContext): WorkflowCon
|
|
|
90
92
|
*/
|
|
91
93
|
export declare function canTransitionTask(from: TaskStatus, to: TaskStatus): boolean;
|
|
92
94
|
|
|
95
|
+
/**
|
|
96
|
+
* Capture every top-level {@link WorkflowOptions} value exactly once into an owned plain bag.
|
|
97
|
+
*
|
|
98
|
+
* @remarks
|
|
99
|
+
* Direct property reads preserve inherited and non-enumerable option values while preventing
|
|
100
|
+
* accessor-backed caller bags from shifting policy, handlers, hooks, or nested options between
|
|
101
|
+
* construction stages. Nested bags and the functions registry retain their original identities so
|
|
102
|
+
* entity constructors can snapshot keyed child options and live additions can resolve against the
|
|
103
|
+
* same registry.
|
|
104
|
+
*
|
|
105
|
+
* @param options - The caller-owned workflow construction options
|
|
106
|
+
* @returns An owned top-level options bag containing the captured values
|
|
107
|
+
*
|
|
108
|
+
* @example
|
|
109
|
+
* ```ts
|
|
110
|
+
* const captured = captureWorkflowOptions(options)
|
|
111
|
+
* const workflow = createWorkflow(definition, captured)
|
|
112
|
+
* ```
|
|
113
|
+
*/
|
|
114
|
+
export declare function captureWorkflowOptions(options?: WorkflowOptions): WorkflowOptions;
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Validate and clone one complete task activity frame.
|
|
118
|
+
*
|
|
119
|
+
* @remarks
|
|
120
|
+
* This is the hostile boundary behind task reports and snapshot hydration. Supplying
|
|
121
|
+
* `updated` stamps an input frame without reading an `updated` property from it; omitting
|
|
122
|
+
* `updated` restores a stored frame and reads its persisted timestamp exactly once. Every
|
|
123
|
+
* untrusted property is captured once inside one protected boundary. The returned frame,
|
|
124
|
+
* collections, progress, operations, and constraints are copied and frozen.
|
|
125
|
+
*
|
|
126
|
+
* @param input - The untrusted complete activity frame
|
|
127
|
+
* @param updated - An optional accepted timestamp used instead of a persisted `updated`
|
|
128
|
+
* @returns An immutable cloned {@link TaskActivity}
|
|
129
|
+
* @throws {WorkflowError} With `MUTATION` when the frame cannot be read or validated
|
|
130
|
+
*/
|
|
131
|
+
export declare function cloneTaskActivity(input: unknown, updated?: number): TaskActivity;
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Validate and own a workflow snapshot before live construction.
|
|
135
|
+
*
|
|
136
|
+
* @param input - The hostile snapshot boundary
|
|
137
|
+
* @param id - The optional storage key the owned snapshot must match
|
|
138
|
+
* @returns A deeply owned frozen snapshot
|
|
139
|
+
* @throws {WorkflowError} With `RESTORE` when the snapshot is invalid or does not match `id`
|
|
140
|
+
*/
|
|
141
|
+
export declare function cloneWorkflowSnapshot(input: unknown, id?: string): WorkflowSnapshot;
|
|
142
|
+
|
|
93
143
|
/**
|
|
94
144
|
* Flatten a nested list of per-phase {@link TaskResult} lists into one positional list
|
|
95
145
|
* — the workflow tier of the result tree, built from each phase's `results()`.
|
|
@@ -215,7 +265,7 @@ export declare interface ControllerInterface<TInput, TResult> {
|
|
|
215
265
|
* @remarks
|
|
216
266
|
* Builds a one-table database (`snapshots`, keyed by `id`) over the supplied driver, the snapshot
|
|
217
267
|
* held as ONE OPAQUE JSON COLUMN — the column map is `{ id; snapshot }` where `snapshot` is a
|
|
218
|
-
* `rawShape` (a JSON blob), exactly as
|
|
268
|
+
* `rawShape` (a JSON blob), exactly as `createDatabaseQueueStore` stores its `input`. The
|
|
219
269
|
* snapshot is already a COMPLETE, self-contained, pure-JSON payload, so storing it whole is lossless
|
|
220
270
|
* AND keeps the row type FLAT — a structured multi-column snapshot table would force the contract to
|
|
221
271
|
* `Infer` the deeply-nested snapshot shape (workflow → phases → tasks → results) and trip TS2589;
|
|
@@ -231,7 +281,8 @@ export declare interface ControllerInterface<TInput, TResult> {
|
|
|
231
281
|
*
|
|
232
282
|
* @example
|
|
233
283
|
* ```ts
|
|
234
|
-
* import {
|
|
284
|
+
* import { createMemoryDriver } from '@orkestrel/database'
|
|
285
|
+
* import { createDatabaseWorkflowStore, createWorkflow, restoreWorkflow } from '@orkestrel/workflow'
|
|
235
286
|
*
|
|
236
287
|
* const store = createDatabaseWorkflowStore(createMemoryDriver()) // a durable driver swaps in here
|
|
237
288
|
* const workflow = createWorkflow(definition)
|
|
@@ -258,7 +309,7 @@ export declare function createDeferred<T>(): DeferredInterface<T>;
|
|
|
258
309
|
*
|
|
259
310
|
* @remarks
|
|
260
311
|
* The snapshot analogue of the server package's `createMemorySessionStore`
|
|
261
|
-
* (and the
|
|
312
|
+
* (and the `createMemoryQueueStore` family), but LEANER — there is no idle-TTL, so no
|
|
262
313
|
* options bag (AGENTS §21 minimal): a persisted run-state lives until an explicit `delete`. This is
|
|
263
314
|
* the zero-plumbing DEFAULT (a plain `Map`); its driver-pluggable twin is
|
|
264
315
|
* {@link createDatabaseWorkflowStore} (the snapshot as one opaque JSON column over a `databases`
|
|
@@ -270,7 +321,7 @@ export declare function createDeferred<T>(): DeferredInterface<T>;
|
|
|
270
321
|
*
|
|
271
322
|
* @example
|
|
272
323
|
* ```ts
|
|
273
|
-
* import { createMemoryWorkflowStore, createWorkflow, restoreWorkflow } from '@
|
|
324
|
+
* import { createMemoryWorkflowStore, createWorkflow, restoreWorkflow } from '@orkestrel/workflow'
|
|
274
325
|
*
|
|
275
326
|
* const store = createMemoryWorkflowStore()
|
|
276
327
|
* const workflow = createWorkflow(definition)
|
|
@@ -310,7 +361,7 @@ export declare function createMemoryWorkflowStore(): WorkflowStoreInterface;
|
|
|
310
361
|
*
|
|
311
362
|
* @example
|
|
312
363
|
* ```ts
|
|
313
|
-
* import { createRunner } from '@
|
|
364
|
+
* import { createRunner } from '@orkestrel/workflow'
|
|
314
365
|
*
|
|
315
366
|
* // A handler that fans out one sibling per declared unit, then returns its own value.
|
|
316
367
|
* const runner = createRunner<number, number>({
|
|
@@ -336,7 +387,8 @@ export declare function createRunner<TInput, TResult>(options: RunnerOptions<TIn
|
|
|
336
387
|
* `yield()` gives the host a turn via a zero-delay macrotask (so pending I/O,
|
|
337
388
|
* timers, and rendering actually run — a microtask would not); `delay(ms)` resumes
|
|
338
389
|
* after at least `ms`. Pass `options.signal` to make a pending yield/delay reject
|
|
339
|
-
* with the signal's `reason
|
|
390
|
+
* with the signal's exact `reason`; the shared owned-signal lifecycle clears the timer
|
|
391
|
+
* without invoking caller-owned listener methods.
|
|
340
392
|
* `options.priority` is accepted for contract compliance but treated uniformly by
|
|
341
393
|
* this default — environment backends honour it.
|
|
342
394
|
*
|
|
@@ -344,7 +396,8 @@ export declare function createRunner<TInput, TResult>(options: RunnerOptions<TIn
|
|
|
344
396
|
*
|
|
345
397
|
* @example
|
|
346
398
|
* ```ts
|
|
347
|
-
* import { createAbort
|
|
399
|
+
* import { createAbort } from '@orkestrel/abort'
|
|
400
|
+
* import { createScheduler } from '@orkestrel/workflow'
|
|
348
401
|
*
|
|
349
402
|
* const abort = createAbort()
|
|
350
403
|
* const scheduler = createScheduler()
|
|
@@ -358,7 +411,7 @@ export declare function createRunner<TInput, TResult>(options: RunnerOptions<TIn
|
|
|
358
411
|
*
|
|
359
412
|
* @example
|
|
360
413
|
* ```ts
|
|
361
|
-
* import { createScheduler } from '@
|
|
414
|
+
* import { createScheduler } from '@orkestrel/workflow'
|
|
362
415
|
*
|
|
363
416
|
* // A backoff: wait a growing interval between retries.
|
|
364
417
|
* const scheduler = createScheduler()
|
|
@@ -388,8 +441,8 @@ export declare function createScheduler(): SchedulerInterface;
|
|
|
388
441
|
*
|
|
389
442
|
* `options.functions` is the {@link import('./types.js').WorkflowFunctions} registry each live
|
|
390
443
|
* task's `run` name resolves against ONCE at construction into its runtime
|
|
391
|
-
* {@link import('./types.js').TaskInterface.handler}
|
|
392
|
-
*
|
|
444
|
+
* {@link import('./types.js').TaskInterface.handler}. An omitted name is the deliberate no-op;
|
|
445
|
+
* an unresolved present name remains inspectable but is rejected if execution is attempted.
|
|
393
446
|
*
|
|
394
447
|
* @param definition - The workflow definition to bring to life
|
|
395
448
|
* @param options - Runtime options (initial listeners, `bail` override, per-node options)
|
|
@@ -397,7 +450,7 @@ export declare function createScheduler(): SchedulerInterface;
|
|
|
397
450
|
*
|
|
398
451
|
* @example
|
|
399
452
|
* ```ts
|
|
400
|
-
* import { createWorkflow } from '@
|
|
453
|
+
* import { createWorkflow } from '@orkestrel/workflow'
|
|
401
454
|
*
|
|
402
455
|
* const workflow = createWorkflow(definition, { on: { complete: () => done() } })
|
|
403
456
|
* const phase = workflow.phase('phase-build')
|
|
@@ -425,7 +478,7 @@ export declare function createWorkflow(definition: WorkflowDefinition, options?:
|
|
|
425
478
|
*
|
|
426
479
|
* @example
|
|
427
480
|
* ```ts
|
|
428
|
-
* import { createWorkflowContract } from '@
|
|
481
|
+
* import { createWorkflowContract } from '@orkestrel/workflow'
|
|
429
482
|
*
|
|
430
483
|
* const contract = createWorkflowContract()
|
|
431
484
|
* const definition = contract.generate() // a valid WorkflowDefinition
|
|
@@ -455,7 +508,7 @@ export declare function createWorkflowContract(): ContractInterface<WorkflowDefi
|
|
|
455
508
|
*
|
|
456
509
|
* @example
|
|
457
510
|
* ```ts
|
|
458
|
-
* import { createMemoryWorkflowStore, createWorkflowManager } from '@
|
|
511
|
+
* import { createMemoryWorkflowStore, createWorkflowManager } from '@orkestrel/workflow'
|
|
459
512
|
*
|
|
460
513
|
* const manager = createWorkflowManager({
|
|
461
514
|
* store: createMemoryWorkflowStore(),
|
|
@@ -475,7 +528,7 @@ export declare function createWorkflowManager(options?: WorkflowManagerOptions):
|
|
|
475
528
|
*
|
|
476
529
|
* @remarks
|
|
477
530
|
* The runner is a PURE engine — it re-implements no concurrency / retry / abort logic, AND it
|
|
478
|
-
* carries no
|
|
531
|
+
* carries no behavior or provider registry of its own: each live task already
|
|
479
532
|
* resolved its own {@link import('./types.js').WorkflowFunction} into
|
|
480
533
|
* {@link import('./types.js').TaskInterface.handler} ONCE at construction, from the
|
|
481
534
|
* {@link WorkflowOptions.functions} registry supplied to `execute` / {@link createWorkflow}.
|
|
@@ -489,11 +542,10 @@ export declare function createWorkflowManager(options?: WorkflowManagerOptions):
|
|
|
489
542
|
* the live entity (`start` → `complete` / `fail`), and resolves a
|
|
490
543
|
* {@link import('./types.js').WorkflowResult}.
|
|
491
544
|
*
|
|
492
|
-
*
|
|
493
|
-
* {@link import('./types.js').WorkflowFunction} into its
|
|
494
|
-
* registry
|
|
495
|
-
*
|
|
496
|
-
* (the ROADMAP no-handler rule).
|
|
545
|
+
* External integrations remain application-owned: a caller wires an ordinary
|
|
546
|
+
* {@link import('./types.js').WorkflowFunction} into its own {@link WorkflowOptions.functions}
|
|
547
|
+
* registry. Only a task that omits `run` auto-completes; unresolved named work is rejected
|
|
548
|
+
* before dispatch.
|
|
497
549
|
*
|
|
498
550
|
* @param options - An optional pacing `scheduler` (default the shipped cross-environment one).
|
|
499
551
|
* See {@link WorkflowRunnerOptions}.
|
|
@@ -501,7 +553,7 @@ export declare function createWorkflowManager(options?: WorkflowManagerOptions):
|
|
|
501
553
|
*
|
|
502
554
|
* @example
|
|
503
555
|
* ```ts
|
|
504
|
-
* import { createWorkflowRunner } from '@
|
|
556
|
+
* import { createWorkflowRunner } from '@orkestrel/workflow'
|
|
505
557
|
*
|
|
506
558
|
* const runner = createWorkflowRunner()
|
|
507
559
|
* const definition = { id: 'w', name: 'W', phases: [{ id: 'p', name: 'P', tasks: [
|
|
@@ -543,7 +595,8 @@ export declare function createWorkflowRunner(options?: WorkflowRunnerOptions): W
|
|
|
543
595
|
* the row `{ id: snapshot.id, snapshot }`.
|
|
544
596
|
* - **`get(id)` resolves the stored snapshot for an id**, narrowing the opaque JSON column back to
|
|
545
597
|
* a {@link WorkflowSnapshot} ({@link import('../helpers.js').isWorkflowSnapshot} — the AGENTS §14
|
|
546
|
-
* boundary narrow for an untrusted storage read), or `undefined` if none is stored.
|
|
598
|
+
* boundary narrow for an untrusted storage read), or `undefined` if none is stored. A present
|
|
599
|
+
* snapshot whose own id differs from the requested key rejects with normalized `RESTORE` evidence.
|
|
547
600
|
* - **`delete(id)` drops a snapshot by id**; an absent id is a no-op (no throw).
|
|
548
601
|
*
|
|
549
602
|
* UNLIKE the server package's `SessionStoreInterface` there is NO
|
|
@@ -554,7 +607,8 @@ export declare function createWorkflowRunner(options?: WorkflowRunnerOptions): W
|
|
|
554
607
|
*
|
|
555
608
|
* @example
|
|
556
609
|
* ```ts
|
|
557
|
-
* import {
|
|
610
|
+
* import { createMemoryDriver } from '@orkestrel/database'
|
|
611
|
+
* import { createDatabaseWorkflowStore, createWorkflow, restoreWorkflow } from '@orkestrel/workflow'
|
|
558
612
|
*
|
|
559
613
|
* const store = createDatabaseWorkflowStore(createMemoryDriver()) // a durable driver swaps in here
|
|
560
614
|
* const workflow = createWorkflow(definition)
|
|
@@ -573,7 +627,7 @@ export declare class DatabaseWorkflowStore implements WorkflowStoreInterface {
|
|
|
573
627
|
* {@link WorkflowSnapshotRow} `{ id; snapshot }` shape (the snapshot one opaque JSON column)
|
|
574
628
|
*/
|
|
575
629
|
constructor(table: TableInterface<WorkflowSnapshotRow>);
|
|
576
|
-
/** Resolve the
|
|
630
|
+
/** Resolve and key-check the snapshot for `id`, narrowing the opaque column to `WorkflowSnapshot`. */
|
|
577
631
|
get(id: string): Promise<WorkflowSnapshot | undefined>;
|
|
578
632
|
/** Insert or replace under the snapshot's OWN `id` (no separate id param) — the row is `{ id, snapshot }`. */
|
|
579
633
|
set(snapshot: WorkflowSnapshot): Promise<void>;
|
|
@@ -728,6 +782,14 @@ export declare function derivePhaseStatus(tasks: readonly TaskStatus[]): PhaseSt
|
|
|
728
782
|
*/
|
|
729
783
|
export declare function deriveWorkflowStatus(phases: readonly PhaseDerivation[]): WorkflowStatus;
|
|
730
784
|
|
|
785
|
+
/**
|
|
786
|
+
* Normalize an unknown thrown value to a non-empty persistence-safe message.
|
|
787
|
+
*
|
|
788
|
+
* @param error - The caught value
|
|
789
|
+
* @returns A non-empty message without stack or cause data
|
|
790
|
+
*/
|
|
791
|
+
export declare function errorToMessage(error: unknown): string;
|
|
792
|
+
|
|
731
793
|
/**
|
|
732
794
|
* Box an error as a {@link Failure} — the graceful outcome half of a {@link Result}.
|
|
733
795
|
*
|
|
@@ -765,6 +827,20 @@ export declare function failure<E>(error: E): Failure<E>;
|
|
|
765
827
|
*/
|
|
766
828
|
export declare function findFailure(results: readonly TaskResult[]): TaskResult | undefined;
|
|
767
829
|
|
|
830
|
+
/**
|
|
831
|
+
* Test that every named task has a callable runtime handler before dispatch.
|
|
832
|
+
*
|
|
833
|
+
* @remarks
|
|
834
|
+
* A snapshot lookup reads each unique `run` binding at most once from `functions`. A live workflow
|
|
835
|
+
* validates its tasks' already-resolved handlers without consulting the retained registry again.
|
|
836
|
+
*
|
|
837
|
+
* @param workflow - The persisted snapshot or constructed live workflow to validate
|
|
838
|
+
* @returns Whether every named task resolves to a callable handler
|
|
839
|
+
*/
|
|
840
|
+
export declare function hasWorkflowHandlers(workflow: WorkflowInterface): boolean;
|
|
841
|
+
|
|
842
|
+
export declare function hasWorkflowHandlers(workflow: WorkflowSnapshot, functions: WorkflowFunctions | undefined): boolean;
|
|
843
|
+
|
|
768
844
|
/**
|
|
769
845
|
* Insert one `[key, value]` entry at a positional index into a readonly entries array —
|
|
770
846
|
* the pure splice-in step behind an insertion-ordered registry's `add`.
|
|
@@ -791,6 +867,34 @@ export declare function findFailure(results: readonly TaskResult[]): TaskResult
|
|
|
791
867
|
*/
|
|
792
868
|
export declare function insertEntry<T>(entries: readonly (readonly [string, T])[], index: number, key: string, value: T): readonly (readonly [string, T])[];
|
|
793
869
|
|
|
870
|
+
/** Test the workflow lifecycle vocabulary. */
|
|
871
|
+
export declare function isLifecycleStatus(value: unknown): value is LifecycleStatus;
|
|
872
|
+
|
|
873
|
+
/**
|
|
874
|
+
* Validate a safe owned JSON graph as a coherent workflow snapshot.
|
|
875
|
+
*
|
|
876
|
+
* @remarks
|
|
877
|
+
* Callers at hostile boundaries use {@link isWorkflowSnapshot}, which owns the
|
|
878
|
+
* graph first so this semantic pass never observes accessors or prototypes.
|
|
879
|
+
*/
|
|
880
|
+
export declare function isOwnedWorkflowSnapshot(value: unknown): value is WorkflowSnapshot;
|
|
881
|
+
|
|
882
|
+
/**
|
|
883
|
+
* Test whether an unknown value is valid persisted task activity.
|
|
884
|
+
*/
|
|
885
|
+
export declare function isTaskActivity(value: unknown): value is TaskActivity;
|
|
886
|
+
|
|
887
|
+
/**
|
|
888
|
+
* Test whether an unknown value is a valid whole-frame activity report.
|
|
889
|
+
*/
|
|
890
|
+
export declare function isTaskActivityInput(value: unknown): value is TaskActivityInput;
|
|
891
|
+
|
|
892
|
+
/** Test a normalized persisted task failure. */
|
|
893
|
+
export declare function isTaskFailure(value: unknown): value is TaskFailure;
|
|
894
|
+
|
|
895
|
+
/** Test a result's lineage against its containing snapshot nodes. */
|
|
896
|
+
export declare function isTaskResult(value: unknown, workflow: unknown, phase: unknown, task: unknown): value is TaskResult;
|
|
897
|
+
|
|
794
898
|
/**
|
|
795
899
|
* Test whether a {@link LifecycleStatus} is TERMINAL — a node in this state will not
|
|
796
900
|
* transition further.
|
|
@@ -825,24 +929,7 @@ export declare function isTerminalStatus(status: LifecycleStatus): boolean;
|
|
|
825
929
|
*/
|
|
826
930
|
export declare function isWorkflowError(value: unknown): value is WorkflowError;
|
|
827
931
|
|
|
828
|
-
/**
|
|
829
|
-
* Narrow an `unknown` to a {@link WorkflowSnapshot} — the AGENTS §14 boundary guard for an
|
|
830
|
-
* UNTRUSTED snapshot read (a storage row a {@link import('./stores/DatabaseWorkflowStore.js').DatabaseWorkflowStore}
|
|
831
|
-
* reads back from its opaque JSON column, a snapshot loaded from disk).
|
|
832
|
-
*
|
|
833
|
-
* @remarks
|
|
834
|
-
* A total guard (it NEVER throws — adversarial input returns `false`, AGENTS §14). It checks the
|
|
835
|
-
* snapshot's SHAPE — `id` / `name` / `status` strings, a `boolean` `bail`, an array of `phases`,
|
|
836
|
-
* `created` / `updated` numbers — enough to safely impose the {@link WorkflowSnapshot} type at a
|
|
837
|
-
* storage boundary WITHOUT a cast. It is complementary to
|
|
838
|
-
* {@link import('./factories.js').assertSnapshot}, which validates the DEEPER invariant (every
|
|
839
|
-
* node's status / override drawn from the lifecycle vocabulary) and THROWS a `RESTORE`
|
|
840
|
-
* {@link import('./errors.js').WorkflowError} — the deep gate a {@link import('./factories.js').restoreWorkflow}
|
|
841
|
-
* applies. A boundary read narrows shape with this guard; a restore validates vocabulary with `assertSnapshot`.
|
|
842
|
-
*
|
|
843
|
-
* @param value - The value to test (an opaque storage read)
|
|
844
|
-
* @returns `true` when `value` has the structural shape of a {@link WorkflowSnapshot}
|
|
845
|
-
*/
|
|
932
|
+
/** Total hostile-boundary workflow snapshot guard. */
|
|
846
933
|
export declare function isWorkflowSnapshot(value: unknown): value is WorkflowSnapshot;
|
|
847
934
|
|
|
848
935
|
/**
|
|
@@ -861,6 +948,14 @@ export declare function isWorkflowSnapshot(value: unknown): value is WorkflowSna
|
|
|
861
948
|
*/
|
|
862
949
|
export declare type LifecycleStatus = 'pending' | 'running' | 'completed' | 'failed' | 'skipped' | 'stopped';
|
|
863
950
|
|
|
951
|
+
/** Compare two optional description values. */
|
|
952
|
+
export declare function matchesDescription(left: unknown, right: unknown): boolean;
|
|
953
|
+
|
|
954
|
+
/**
|
|
955
|
+
* The largest delay representable by the host timer APIs without overflow or clamping.
|
|
956
|
+
*/
|
|
957
|
+
export declare const MAX_TIMER_MS = 2147483647;
|
|
958
|
+
|
|
864
959
|
/**
|
|
865
960
|
* The in-memory {@link WorkflowStoreInterface} — a process-lifetime `Map` of
|
|
866
961
|
* {@link WorkflowSnapshot}s keyed by workflow id, the DEFAULT store
|
|
@@ -889,7 +984,7 @@ export declare type LifecycleStatus = 'pending' | 'running' | 'completed' | 'fai
|
|
|
889
984
|
*
|
|
890
985
|
* @example
|
|
891
986
|
* ```ts
|
|
892
|
-
* import { createMemoryWorkflowStore, createWorkflow, restoreWorkflow } from '@
|
|
987
|
+
* import { createMemoryWorkflowStore, createWorkflow, restoreWorkflow } from '@orkestrel/workflow'
|
|
893
988
|
*
|
|
894
989
|
* const store = createMemoryWorkflowStore()
|
|
895
990
|
* const workflow = createWorkflow(definition)
|
|
@@ -961,9 +1056,9 @@ export declare function parkSignal(signal: AbortSignal): Promise<void>;
|
|
|
961
1056
|
*
|
|
962
1057
|
* @remarks
|
|
963
1058
|
* - **Derived status.** `status` is `#override` when one is in force, else
|
|
964
|
-
* {@link derivePhaseStatus} over the live tasks' statuses.
|
|
1059
|
+
* {@link derivePhaseStatus} over the live tasks' statuses. `#recompute` (passed to
|
|
965
1060
|
* each child {@link Task}) re-derives on every child transition; a CHANGE emits the matching
|
|
966
|
-
* event AND escalates to the workflow (
|
|
1061
|
+
* event AND escalates to the workflow (`#escalate`, the upward step of the cascade).
|
|
967
1062
|
* - **Override (AGENTS §10).** `skip` / `stop` FORCE the phase's status (e.g. skipping a whole
|
|
968
1063
|
* phase), overriding the derived value; the override is PERSISTED in the snapshot's own
|
|
969
1064
|
* `override` field and restored DIRECTLY (no divergence guess), so a forced phase round-trips.
|
|
@@ -972,9 +1067,11 @@ export declare function parkSignal(signal: AbortSignal): Promise<void>;
|
|
|
972
1067
|
* `results()` collects the settled tasks' {@link TaskResult}s (the phase tier of the result
|
|
973
1068
|
* tree); `workflow` navigates UP to the live parent.
|
|
974
1069
|
* - **Observable (AGENTS §13).** The owned {@link emitter} ({@link PhaseEventMap}) fires
|
|
975
|
-
* `start` / `complete` / `fail` / `
|
|
976
|
-
*
|
|
977
|
-
*
|
|
1070
|
+
* `start` / `complete` / `fail` / `pause` / `resume` / `skip` / `stop` after the
|
|
1071
|
+
* corresponding status or runtime-gate change. Status events fire after the phase recomputes
|
|
1072
|
+
* and before it escalates to the workflow, preserving child/phase cause before parent effect.
|
|
1073
|
+
* The emitter isolates a listener throw and routes it to its `error` handler (the `error`
|
|
1074
|
+
* option); `fail` carries the failing task's {@link TaskResult}.
|
|
978
1075
|
* - **Structural API (AGENTS §7).** `add` / `remove` / `move` / `update` gate BEFORE
|
|
979
1076
|
* delegating to {@link tasks} (the manager gates the target's own existence/status/id/
|
|
980
1077
|
* bounds), then emit the matching {@link PhaseEventMap} event on success only. NATIVE
|
|
@@ -992,9 +1089,12 @@ export declare function parkSignal(signal: AbortSignal): Promise<void>;
|
|
|
992
1089
|
* construction path {@link #append} uses at build time, so a live mint and a restored/built
|
|
993
1090
|
* task are wired IDENTICALLY. At construction, the workflow-level
|
|
994
1091
|
* {@link import('../types.js').WorkflowFunctions} registry (threaded from
|
|
995
|
-
* {@link import('../types.js').WorkflowOptions.functions}) resolves
|
|
996
|
-
*
|
|
997
|
-
*
|
|
1092
|
+
* {@link import('../types.js').WorkflowOptions.functions}) resolves every unique initial `run`
|
|
1093
|
+
* name ONCE before any task is built; siblings sharing a name receive the exact same captured
|
|
1094
|
+
* runtime {@link import('../types.js').TaskInterface.handler}. A later live {@link add} reads
|
|
1095
|
+
* that name once from the retained registry at its own mint moment. An omitted or unregistered
|
|
1096
|
+
* `run` resolves to no handler; only omission is a no-op, while an unresolved present name makes
|
|
1097
|
+
* the containing tree non-drivable.
|
|
998
1098
|
* - **Runtime lifecycle (AGENTS §10).** `pause` / `resume` / `wait` mirror the workflow's own
|
|
999
1099
|
* quartet, scoped to this phase — a driving
|
|
1000
1100
|
* {@link import('../types.js').WorkflowRunnerInterface.execute} gates a task's own
|
|
@@ -1007,7 +1107,7 @@ export declare function parkSignal(signal: AbortSignal): Promise<void>;
|
|
|
1007
1107
|
export declare class Phase implements PhaseInterface {
|
|
1008
1108
|
#private;
|
|
1009
1109
|
readonly description?: string;
|
|
1010
|
-
constructor(snapshot: PhaseSnapshot, workflow: WorkflowInterface, escalate: () => void, options?: PhaseOptions, bail?: boolean, functions?: WorkflowFunctions);
|
|
1110
|
+
constructor(snapshot: PhaseSnapshot, workflow: WorkflowInterface, escalate: () => void, options?: PhaseOptions, bail?: boolean, functions?: WorkflowFunctions, silence?: number);
|
|
1011
1111
|
get emitter(): EmitterInterface<PhaseEventMap>;
|
|
1012
1112
|
get id(): string;
|
|
1013
1113
|
get name(): string;
|
|
@@ -1116,8 +1216,10 @@ export declare interface PhaseDerivation {
|
|
|
1116
1216
|
* @remarks
|
|
1117
1217
|
* `start` fires when the phase begins; `complete` when all its tasks settled
|
|
1118
1218
|
* successfully; `fail` when a task failed under `bail` (carrying the
|
|
1119
|
-
* {@link TaskResult}); `
|
|
1120
|
-
* `
|
|
1219
|
+
* {@link TaskResult}); `pause` / `resume` when its runtime gate closes / opens;
|
|
1220
|
+
* `skip` when the phase was intentionally skipped; `stop` when the phase was ended.
|
|
1221
|
+
* `add` / `remove` / `move` / `update` fire on a successful
|
|
1222
|
+
* structural or patch edit through
|
|
1121
1223
|
* {@link PhaseInterface.add} / `remove` / `move` / `update` (AGENTS §7) — never on a
|
|
1122
1224
|
* refused/gated one. A throwing listener is isolated by the emitter and routed to its
|
|
1123
1225
|
* `error` handler, not the domain surface (AGENTS §13). A `type` alias (AGENTS §4.5)
|
|
@@ -1130,6 +1232,12 @@ export declare type PhaseEventMap = {
|
|
|
1130
1232
|
readonly complete: readonly [];
|
|
1131
1233
|
/** A task failed under `bail` — the failing task's result. */
|
|
1132
1234
|
readonly fail: readonly [result: TaskResult];
|
|
1235
|
+
/** The phase's runtime gate closed. */
|
|
1236
|
+
readonly pause: readonly [];
|
|
1237
|
+
/** The phase's runtime gate opened. */
|
|
1238
|
+
readonly resume: readonly [];
|
|
1239
|
+
/** The phase was intentionally skipped. */
|
|
1240
|
+
readonly skip: readonly [];
|
|
1133
1241
|
/** The phase was permanently stopped. */
|
|
1134
1242
|
readonly stop: readonly [];
|
|
1135
1243
|
/** A task was inserted — the inserted task + its final index. */
|
|
@@ -1165,8 +1273,9 @@ export declare type PhaseInput = Partial<PhaseContext>;
|
|
|
1165
1273
|
* - **Override.** `skip` / `stop` (AGENTS §10) FORCE the phase's status, overriding the
|
|
1166
1274
|
* derived value (e.g. skipping a whole phase); the override survives a snapshot.
|
|
1167
1275
|
* - **Observable (AGENTS §13).** The owned {@link emitter} ({@link PhaseEventMap}) fires
|
|
1168
|
-
* `start` / `complete` / `fail` / `
|
|
1169
|
-
* listener throw and routes it to
|
|
1276
|
+
* `start` / `complete` / `fail` / `pause` / `resume` / `stop` after the corresponding
|
|
1277
|
+
* status or runtime-gate change; the emitter isolates a listener throw and routes it to
|
|
1278
|
+
* its `error` handler (the `error` option).
|
|
1170
1279
|
* - **Runtime lifecycle (AGENTS §10).** `pause` / `resume` / `wait` mirror
|
|
1171
1280
|
* {@link WorkflowInterface.pause} / `resume` / `wait`, scoped to this phase — a driving
|
|
1172
1281
|
* {@link WorkflowRunnerInterface.execute} gates a task's own pre-dispatch on BOTH the
|
|
@@ -1532,10 +1641,10 @@ export declare interface PhaseSnapshot {
|
|
|
1532
1641
|
* derived from its tasks' statuses.
|
|
1533
1642
|
*
|
|
1534
1643
|
* @remarks
|
|
1535
|
-
* A semantic tier of the shared {@link LifecycleStatus} vocabulary. A
|
|
1536
|
-
* `failed`
|
|
1537
|
-
* failure
|
|
1538
|
-
* when every task was stopped. See {@link import('./helpers.js').derivePhaseStatus}.
|
|
1644
|
+
* A semantic tier of the shared {@link LifecycleStatus} vocabulary. A failed task makes
|
|
1645
|
+
* its phase `failed` regardless of policy; the phase's effective `bail` determines whether
|
|
1646
|
+
* that failure propagates to the workflow or is retained as graceful result data. `stopped`
|
|
1647
|
+
* propagates when every task was stopped. See {@link import('./helpers.js').derivePhaseStatus}.
|
|
1539
1648
|
*/
|
|
1540
1649
|
export declare type PhaseStatus = LifecycleStatus;
|
|
1541
1650
|
|
|
@@ -1578,6 +1687,38 @@ export declare const phaseUpdateShape: ObjectShape<{
|
|
|
1578
1687
|
bail: OptionalShape<LiteralShape<readonly [true, false]>>;
|
|
1579
1688
|
}, false>;
|
|
1580
1689
|
|
|
1690
|
+
/**
|
|
1691
|
+
* Rebuild an interrupted workflow at its remaining retry budget.
|
|
1692
|
+
*
|
|
1693
|
+
* @remarks
|
|
1694
|
+
* Each phase captures every unique initial `run` binding once before constructing tasks. Recovery
|
|
1695
|
+
* validates those live tasks' captured callable handlers without rereading the registry, while the
|
|
1696
|
+
* retained registry identity remains available to resolve future live additions at their mint time.
|
|
1697
|
+
*
|
|
1698
|
+
* @param snapshot - The hostile persisted snapshot
|
|
1699
|
+
* @param options - Runtime handlers and entity options
|
|
1700
|
+
* @returns A recoverable live workflow
|
|
1701
|
+
*/
|
|
1702
|
+
export declare function recoverWorkflow(snapshot: unknown, options?: WorkflowOptions): WorkflowInterface;
|
|
1703
|
+
|
|
1704
|
+
/**
|
|
1705
|
+
* Convert interrupted running work into a recoverable pending suffix or an
|
|
1706
|
+
* exhausted recovery failure without replenishing attempts.
|
|
1707
|
+
*
|
|
1708
|
+
* @param snapshot - A fully validated owned snapshot with no terminal overrides
|
|
1709
|
+
* @returns The recovery projection
|
|
1710
|
+
*/
|
|
1711
|
+
export declare function recoverWorkflowSnapshot(snapshot: WorkflowSnapshot): WorkflowSnapshot;
|
|
1712
|
+
|
|
1713
|
+
/**
|
|
1714
|
+
* Resolve a task's runtime silence window against its workflow default.
|
|
1715
|
+
*
|
|
1716
|
+
* @param value - The task-level override; any present non-positive or non-finite value disables
|
|
1717
|
+
* @param fallback - The workflow-level default
|
|
1718
|
+
* @returns A host-safe effective window (`1..MAX_TIMER_MS`), or `undefined`
|
|
1719
|
+
*/
|
|
1720
|
+
export declare function resolveTaskSilence(value: number | undefined, fallback: number | undefined): number | undefined;
|
|
1721
|
+
|
|
1581
1722
|
/**
|
|
1582
1723
|
* Rebuild an equivalent live W-b entity tree from a {@link WorkflowSnapshot} — the
|
|
1583
1724
|
* inverse of {@link WorkflowInterface.snapshot}, restoring structure + each node's status
|
|
@@ -1594,6 +1735,9 @@ export declare const phaseUpdateShape: ObjectShape<{
|
|
|
1594
1735
|
* still wins when supplied (to deliberately re-run under a different policy). A structurally
|
|
1595
1736
|
* invalid snapshot (a status — or override — outside the lifecycle vocabulary, or a
|
|
1596
1737
|
* non-boolean `bail`) throws a `RESTORE` {@link WorkflowError}.
|
|
1738
|
+
* Runtime handlers are optional: without a matching `functions` entry, a persisted `run`
|
|
1739
|
+
* remains visible with an undefined `handler` so the exact state is inspectable. The runner
|
|
1740
|
+
* rejects that unresolved tree if execution is attempted.
|
|
1597
1741
|
*
|
|
1598
1742
|
* @param snapshot - The snapshot to restore (carries its own `bail` + `override`)
|
|
1599
1743
|
* @param options - Runtime options (initial listeners, an optional `bail` override, per-node options)
|
|
@@ -1601,13 +1745,13 @@ export declare const phaseUpdateShape: ObjectShape<{
|
|
|
1601
1745
|
*
|
|
1602
1746
|
* @example
|
|
1603
1747
|
* ```ts
|
|
1604
|
-
* import { restoreWorkflow } from '@
|
|
1748
|
+
* import { restoreWorkflow } from '@orkestrel/workflow'
|
|
1605
1749
|
*
|
|
1606
1750
|
* const restored = restoreWorkflow(workflow.snapshot()) // bail comes from the snapshot
|
|
1607
1751
|
* restored.status === workflow.status // true
|
|
1608
1752
|
* ```
|
|
1609
1753
|
*/
|
|
1610
|
-
export declare function restoreWorkflow(snapshot:
|
|
1754
|
+
export declare function restoreWorkflow(snapshot: unknown, options?: WorkflowOptions): WorkflowInterface;
|
|
1611
1755
|
|
|
1612
1756
|
/**
|
|
1613
1757
|
* A thin generic orchestrator that drives declared units — and any they `spawn` —
|
|
@@ -1696,7 +1840,7 @@ export declare class Runner<TInput, TResult> implements RunnerInterface<TInput,
|
|
|
1696
1840
|
*/
|
|
1697
1841
|
spawn(input: TInput): Promise<TResult> | undefined;
|
|
1698
1842
|
execute(inputs: readonly TInput[]): Promise<readonly TResult[]>;
|
|
1699
|
-
abort(reason?: unknown): void
|
|
1843
|
+
abort(reason?: unknown): Promise<void>;
|
|
1700
1844
|
/**
|
|
1701
1845
|
* Suspend dispatch (AGENTS §10 — resumable): delegates to the backing queue's own
|
|
1702
1846
|
* `pause`, which holds the NEXT dispatch while any in-flight unit finishes.
|
|
@@ -1726,8 +1870,8 @@ export declare class Runner<TInput, TResult> implements RunnerInterface<TInput,
|
|
|
1726
1870
|
* gate, no recorded failure, no fail-fast trip) rather than a genuine failure — a
|
|
1727
1871
|
* dispatched unit's rejection while stopping is still a real failure. Idempotent.
|
|
1728
1872
|
*/
|
|
1729
|
-
stop(): void
|
|
1730
|
-
destroy(): void
|
|
1873
|
+
stop(): Promise<void>;
|
|
1874
|
+
destroy(): Promise<void>;
|
|
1731
1875
|
}
|
|
1732
1876
|
|
|
1733
1877
|
/**
|
|
@@ -1859,8 +2003,9 @@ export declare interface RunnerInterface<TInput, TResult> {
|
|
|
1859
2003
|
* `execute` reject.
|
|
1860
2004
|
*
|
|
1861
2005
|
* @param reason - An optional cancellation reason propagated to every unit's signal
|
|
2006
|
+
* @returns The stable cleanup barrier
|
|
1862
2007
|
*/
|
|
1863
|
-
abort(reason?: unknown): void
|
|
2008
|
+
abort(reason?: unknown): Promise<void>;
|
|
1864
2009
|
/**
|
|
1865
2010
|
* Suspend dispatch (AGENTS §10 — resumable): the backing queue holds the NEXT dispatch
|
|
1866
2011
|
* while any in-flight unit finishes; idempotent.
|
|
@@ -1897,10 +2042,15 @@ export declare interface RunnerInterface<TInput, TResult> {
|
|
|
1897
2042
|
* runner.stop() // the in-flight unit finishes; the rest are gracefully dropped
|
|
1898
2043
|
* await results // resolves with whatever settled — never rejects
|
|
1899
2044
|
* ```
|
|
2045
|
+
* @returns The stable graceful-cleanup barrier
|
|
1900
2046
|
*/
|
|
1901
|
-
stop(): void
|
|
1902
|
-
/**
|
|
1903
|
-
|
|
2047
|
+
stop(): Promise<void>;
|
|
2048
|
+
/**
|
|
2049
|
+
* Tear the runner down, awaiting backing-queue cleanup before destroying the emitter last.
|
|
2050
|
+
*
|
|
2051
|
+
* @returns The stable teardown barrier
|
|
2052
|
+
*/
|
|
2053
|
+
destroy(): Promise<void>;
|
|
1904
2054
|
}
|
|
1905
2055
|
|
|
1906
2056
|
/**
|
|
@@ -1910,11 +2060,11 @@ export declare interface RunnerInterface<TInput, TResult> {
|
|
|
1910
2060
|
* - `handler` — runs each unit's work against its {@link ControllerInterface};
|
|
1911
2061
|
* rejecting fails the unit (and, after retries are exhausted, fails the run).
|
|
1912
2062
|
* - `concurrency` — the maximum units in flight at once; defaults to `1` (ordered,
|
|
1913
|
-
* one-at-a-time)
|
|
2063
|
+
* one-at-a-time) and must be a positive safe integer.
|
|
1914
2064
|
* - `retries` — the default extra attempts per unit on failure (or a per-attempt
|
|
1915
|
-
* timeout); defaults to `0
|
|
1916
|
-
* - `timeout` — the per-attempt deadline in milliseconds; defaults to
|
|
1917
|
-
*
|
|
2065
|
+
* timeout); defaults to `0` and must be a nonnegative safe integer.
|
|
2066
|
+
* - `timeout` — the per-attempt deadline in milliseconds; defaults to `0`, must be
|
|
2067
|
+
* an integer in `0..2_147_483_647`, and `0` disables the deadline.
|
|
1918
2068
|
* - `entries` — per-entry `retries` / `timeout` overrides, resolved from each
|
|
1919
2069
|
* input; falls back to the runner-level `retries` / `timeout` defaults.
|
|
1920
2070
|
* - `on` — the reserved {@link EmitterHooks} key (§8): initial listeners for the runner's
|
|
@@ -1950,6 +2100,25 @@ export declare interface RunnerUnit<TInput> {
|
|
|
1950
2100
|
readonly input: TInput;
|
|
1951
2101
|
}
|
|
1952
2102
|
|
|
2103
|
+
/**
|
|
2104
|
+
* Schedule one cancellable host operation behind an owned settlement signal.
|
|
2105
|
+
*
|
|
2106
|
+
* @remarks
|
|
2107
|
+
* The completion and failure paths each own an {@link AbortController}; their native composite is
|
|
2108
|
+
* linked to the optional caller signal before `start` can arm host work. Scheduler backends attach
|
|
2109
|
+
* only to that safe composite, so caller mutation of `addEventListener` or `removeEventListener`
|
|
2110
|
+
* cannot strand the operation. The first completion resolves, the first host failure rejects with
|
|
2111
|
+
* its exact value, and caller abort rejects with its exact linked reason. Caller abort and host
|
|
2112
|
+
* failure cancel an armed handle; synchronous settlement also cancels the handle immediately after
|
|
2113
|
+
* `start` returns it. Cancellation is secondary cleanup: if its closure throws, the already-winning
|
|
2114
|
+
* completion, exact host failure, or exact caller reason still settles without escape or replacement.
|
|
2115
|
+
*
|
|
2116
|
+
* @param start - Arm host work and return its cancellation closure
|
|
2117
|
+
* @param signal - Optional caller cancellation signal
|
|
2118
|
+
* @returns A promise settled exactly once by completion, host failure, or caller abort
|
|
2119
|
+
*/
|
|
2120
|
+
export declare function scheduleHost(start: (complete: () => void, failure: (error: unknown) => void) => () => void, signal?: AbortSignal): Promise<void>;
|
|
2121
|
+
|
|
1953
2122
|
/**
|
|
1954
2123
|
* The safe cross-environment cooperative-yield default — a {@link SchedulerInterface}
|
|
1955
2124
|
* built on `setTimeout` / `clearTimeout` alone, so it runs unchanged in both the
|
|
@@ -1966,11 +2135,10 @@ export declare interface RunnerUnit<TInput> {
|
|
|
1966
2135
|
* regains control, so it would not actually let pending I/O, timers, or
|
|
1967
2136
|
* rendering run — it only defers within the current task. A zero-delay timer is
|
|
1968
2137
|
* the correct cross-environment "give the host a turn".
|
|
1969
|
-
* - **Abort-aware.** A pending `yield` / `delay` rejects with `signal.reason`
|
|
1970
|
-
*
|
|
1971
|
-
*
|
|
1972
|
-
*
|
|
1973
|
-
* listener, and no double-settle.
|
|
2138
|
+
* - **Abort-aware.** A pending `yield` / `delay` rejects with `signal.reason` exactly.
|
|
2139
|
+
* {@link scheduleHost} links an owned settlement composite to the caller before arming
|
|
2140
|
+
* the timer, so pre-abort schedules nothing, caller signal method mutation is harmless,
|
|
2141
|
+
* cancellation clears the handle, and native first-settlement wins exactly once.
|
|
1974
2142
|
* - **Priority is accepted but uniform.** `options.priority` is part of the
|
|
1975
2143
|
* contract, but a `setTimeout`-based default cannot act on urgency, so it treats
|
|
1976
2144
|
* every priority the same. Environment backends honour it.
|
|
@@ -2065,9 +2233,8 @@ export declare function success<T>(value: T): Success<T>;
|
|
|
2065
2233
|
* `TRANSITION` {@link WorkflowError} on an illegal move (e.g. completing a non-`running`
|
|
2066
2234
|
* task) — the legal graph is the single source of truth, so the leaf can never reach an
|
|
2067
2235
|
* impossible state.
|
|
2068
|
-
* - **
|
|
2069
|
-
*
|
|
2070
|
-
* one and reinstate it AS an override — preserving the round-trip.
|
|
2236
|
+
* - **Snapshot fidelity.** A leaf needs no override: `skipped` / `stopped` are explicit terminal
|
|
2237
|
+
* statuses, and restore reinstates the leaf directly from {@link TaskSnapshot.status}.
|
|
2071
2238
|
* - **The cascade.** Every status change records its boxed result (when any), fires the leaf's
|
|
2072
2239
|
* OWN event, THEN calls the parent phase's `#recompute` (injected at construction) so the
|
|
2073
2240
|
* transition propagates UP (Task → Phase → Workflow re-derive). The own-event-before-cascade
|
|
@@ -2082,12 +2249,13 @@ export declare function success<T>(value: T): Success<T>;
|
|
|
2082
2249
|
* matching {@link import('../types.js').TaskDefinition} / {@link TaskSnapshot} field. `handler`
|
|
2083
2250
|
* is the RUNTIME-ONLY counterpart — `run` resolved ONCE at construction against the
|
|
2084
2251
|
* workflow-level {@link import('../types.js').WorkflowOptions.functions} registry — and is
|
|
2085
|
-
* NEVER persisted; `undefined` when `run` is omitted or unregistered
|
|
2252
|
+
* NEVER persisted; `undefined` when `run` is omitted or unregistered. Only omission is a
|
|
2253
|
+
* deliberate no-op; unresolved named work is rejected before dispatch.
|
|
2086
2254
|
*/
|
|
2087
2255
|
export declare class Task implements TaskInterface {
|
|
2088
2256
|
#private;
|
|
2089
2257
|
readonly description?: string;
|
|
2090
|
-
constructor(context: TaskContext, phase: PhaseInterface, workflow: WorkflowInterface, recompute: () => void, options?: TaskOptions, status?: TaskStatus, result?: TaskResult, run?: string, retries?: number, timeout?: number, handler?: WorkflowFunction);
|
|
2258
|
+
constructor(context: TaskContext, phase: PhaseInterface, workflow: WorkflowInterface, recompute: () => void, options?: TaskOptions, status?: TaskStatus, result?: TaskResult, run?: string, retries?: number, timeout?: number, metadata?: JSONRecord, attempts?: number, activity?: TaskActivity, handler?: WorkflowFunction, silence?: number);
|
|
2091
2259
|
get emitter(): EmitterInterface<TaskEventMap>;
|
|
2092
2260
|
get id(): string;
|
|
2093
2261
|
get name(): string;
|
|
@@ -2096,15 +2264,26 @@ export declare class Task implements TaskInterface {
|
|
|
2096
2264
|
get workflow(): WorkflowInterface;
|
|
2097
2265
|
get status(): TaskStatus;
|
|
2098
2266
|
get result(): TaskResult | undefined;
|
|
2267
|
+
get attempts(): number;
|
|
2099
2268
|
get run(): string | undefined;
|
|
2100
2269
|
get handler(): WorkflowFunction | undefined;
|
|
2101
2270
|
get retries(): number | undefined;
|
|
2102
2271
|
get timeout(): number | undefined;
|
|
2272
|
+
get activity(): TaskActivity | undefined;
|
|
2273
|
+
get silence(): number | undefined;
|
|
2274
|
+
get silent(): boolean;
|
|
2275
|
+
get paused(): boolean;
|
|
2276
|
+
get signal(): AbortSignal;
|
|
2103
2277
|
start(): void;
|
|
2104
|
-
complete(value:
|
|
2105
|
-
fail(error:
|
|
2278
|
+
complete(value: JSONValue): void;
|
|
2279
|
+
fail(error: TaskFailure): void;
|
|
2106
2280
|
skip(): void;
|
|
2107
2281
|
stop(): void;
|
|
2282
|
+
report(input: TaskActivityInput): Result<TaskActivity, WorkflowError>;
|
|
2283
|
+
pulse(): boolean;
|
|
2284
|
+
pause(): void;
|
|
2285
|
+
resume(): void;
|
|
2286
|
+
wait(): Promise<void>;
|
|
2108
2287
|
/**
|
|
2109
2288
|
* Apply a validated declarative patch to SELF (`name` / `description`).
|
|
2110
2289
|
*
|
|
@@ -2148,6 +2327,44 @@ export declare const TASK_STATUSES: readonly TaskStatus[];
|
|
|
2148
2327
|
*/
|
|
2149
2328
|
export declare const TASK_TRANSITIONS: Readonly<Record<TaskStatus, readonly TaskStatus[]>>;
|
|
2150
2329
|
|
|
2330
|
+
/**
|
|
2331
|
+
* The bounded, JSON-serializable activity most recently accepted from a task reporter.
|
|
2332
|
+
*/
|
|
2333
|
+
export declare interface TaskActivity {
|
|
2334
|
+
readonly note?: string;
|
|
2335
|
+
readonly progress?: TaskProgress;
|
|
2336
|
+
readonly operations: readonly TaskOperation[];
|
|
2337
|
+
readonly constraints: readonly TaskConstraint[];
|
|
2338
|
+
readonly updated: number;
|
|
2339
|
+
}
|
|
2340
|
+
|
|
2341
|
+
/**
|
|
2342
|
+
* One complete replacement of a running task's observable activity.
|
|
2343
|
+
*
|
|
2344
|
+
* @remarks
|
|
2345
|
+
* Omitted `operations` or `constraints` mean an empty list. Omitted `progress` clears the
|
|
2346
|
+
* previous aggregate progress. Use {@link TaskInterface.report} to commit the replacement.
|
|
2347
|
+
*/
|
|
2348
|
+
export declare interface TaskActivityInput {
|
|
2349
|
+
readonly note?: string;
|
|
2350
|
+
readonly progress?: TaskProgress;
|
|
2351
|
+
readonly operations?: readonly TaskOperation[];
|
|
2352
|
+
readonly constraints?: readonly TaskConstraint[];
|
|
2353
|
+
}
|
|
2354
|
+
|
|
2355
|
+
/**
|
|
2356
|
+
* One constraint claimed active when a running task's complete frame was accepted.
|
|
2357
|
+
*
|
|
2358
|
+
* @remarks
|
|
2359
|
+
* Constraints describe active limits or requirements without embedding provider policy in
|
|
2360
|
+
* core. `id` is unique within one complete report and `started` is finite and non-negative.
|
|
2361
|
+
*/
|
|
2362
|
+
export declare interface TaskConstraint {
|
|
2363
|
+
readonly id: string;
|
|
2364
|
+
readonly name: string;
|
|
2365
|
+
readonly started: number;
|
|
2366
|
+
}
|
|
2367
|
+
|
|
2151
2368
|
/**
|
|
2152
2369
|
* The ambient context of a task — its own identity plus a back-reference to the
|
|
2153
2370
|
* phase (and, transitively, the workflow) it belongs to.
|
|
@@ -2162,18 +2379,17 @@ export declare interface TaskContext extends WorkflowContext {
|
|
|
2162
2379
|
}
|
|
2163
2380
|
|
|
2164
2381
|
/**
|
|
2165
|
-
* The
|
|
2166
|
-
* running task's folded cancellation, its input, its lineage, and read-UP access to the
|
|
2167
|
-
* result tree.
|
|
2382
|
+
* The attempt-scoped handle a {@link import('./types.js').WorkflowFunction} receives.
|
|
2168
2383
|
*
|
|
2169
2384
|
* @remarks
|
|
2170
2385
|
* - **A leaf handle, NOT the runner `Controller`.** A workflow task is a leaf of the
|
|
2171
|
-
* declarative W-b tree, not a fan-out unit, so
|
|
2172
|
-
*
|
|
2173
|
-
* - **Folded signal.** `signal` is the cancellation
|
|
2174
|
-
*
|
|
2175
|
-
*
|
|
2176
|
-
*
|
|
2386
|
+
* declarative W-b tree, not a fan-out unit, so it has no `spawn`; its `wait` instead
|
|
2387
|
+
* checkpoints the workflow, phase, and task cooperative gates.
|
|
2388
|
+
* - **Folded signal.** `signal` is the cancellation folded for THIS attempt: its per-attempt
|
|
2389
|
+
* deadline, task stop/skip, workflow abort/timeout/budget/destroy, or a sibling fail-fast.
|
|
2390
|
+
* A handler races its work against it; `aborted` reads it.
|
|
2391
|
+
* - **Attempt ownership.** `report` / `pulse` are closures supplied by the runner and refuse
|
|
2392
|
+
* after this signal aborts or a retry token supersedes this handle.
|
|
2177
2393
|
* - **Input + lineage.** `input` is the task's open `metadata` bag (its
|
|
2178
2394
|
* {@link import('./types.js').TaskInput} payload, `{}` when none); `task` is the full
|
|
2179
2395
|
* {@link TaskContext}, so `task.phase` / `task.phase.workflow` navigate UP the lineage.
|
|
@@ -2188,10 +2404,15 @@ export declare interface TaskContext extends WorkflowContext {
|
|
|
2188
2404
|
declare class TaskController_2 implements TaskControllerInterface {
|
|
2189
2405
|
#private;
|
|
2190
2406
|
readonly signal: AbortSignal;
|
|
2191
|
-
readonly input:
|
|
2407
|
+
readonly input: JSONRecord;
|
|
2192
2408
|
readonly task: TaskContext;
|
|
2193
|
-
|
|
2409
|
+
readonly attempt: number;
|
|
2410
|
+
constructor(signal: AbortSignal, input: JSONRecord, task: TaskInterface, attempt: number, results: () => readonly TaskResult[], report: (input: TaskActivityInput) => Result<TaskActivity, WorkflowError>, pulse: () => boolean);
|
|
2194
2411
|
get aborted(): boolean;
|
|
2412
|
+
get paused(): boolean;
|
|
2413
|
+
report(input: TaskActivityInput): Result<TaskActivity, WorkflowError>;
|
|
2414
|
+
pulse(): boolean;
|
|
2415
|
+
wait(): Promise<void>;
|
|
2195
2416
|
results(): readonly TaskResult[];
|
|
2196
2417
|
}
|
|
2197
2418
|
export { TaskController_2 as TaskController }
|
|
@@ -2201,26 +2422,49 @@ export { TaskController_2 as TaskController }
|
|
|
2201
2422
|
* cancellation, its input, its lineage, and read-UP access to the result tree.
|
|
2202
2423
|
*
|
|
2203
2424
|
* @remarks
|
|
2204
|
-
* A NEW, lean handle (NOT the runner `Controller` — it carries no `spawn
|
|
2205
|
-
*
|
|
2206
|
-
* - `signal` —
|
|
2207
|
-
*
|
|
2208
|
-
* runner aborts the in-flight siblings). A handler races its work against it.
|
|
2425
|
+
* A NEW, lean handle (NOT the runner `Controller` — it carries no `spawn`; a workflow task
|
|
2426
|
+
* is a leaf of the declarative tree, not a fan-out unit). It exposes:
|
|
2427
|
+
* - `signal` — this attempt's folded cancellation: its per-attempt deadline, task
|
|
2428
|
+
* stop/skip, workflow abort/timeout/budget/destroy, or a sibling fail-fast.
|
|
2209
2429
|
* - `aborted` — whether `signal` has fired.
|
|
2210
2430
|
* - `input` — the task's `metadata` bag (the open consumer payload from its
|
|
2211
2431
|
* {@link TaskInput}); `{}` when none.
|
|
2212
2432
|
* - `task` — the task's full {@link TaskContext} (so `task.phase` / `task.phase.workflow`
|
|
2213
2433
|
* navigate UP the lineage).
|
|
2434
|
+
* - `wait()` — a cooperative checkpoint for the workflow, phase, and task pause gates.
|
|
2214
2435
|
* - `results()` — every settled task's {@link TaskResult} across already-finished phases,
|
|
2215
2436
|
* so a `function` task can read an earlier phase's output (the W-b result tree, read-only).
|
|
2216
2437
|
*/
|
|
2217
2438
|
export declare interface TaskControllerInterface {
|
|
2218
|
-
/** Fires on
|
|
2439
|
+
/** Fires on this attempt's deadline, task stop/skip, run cancellation, or sibling fail-fast. */
|
|
2219
2440
|
readonly signal: AbortSignal;
|
|
2220
2441
|
readonly aborted: boolean;
|
|
2221
2442
|
/** The task's open `metadata` bag (its {@link TaskInput} payload); `{}` when none. */
|
|
2222
|
-
readonly input:
|
|
2443
|
+
readonly input: JSONRecord;
|
|
2223
2444
|
readonly task: TaskContext;
|
|
2445
|
+
/** The one-based persisted launch represented by this handle. */
|
|
2446
|
+
readonly attempt: number;
|
|
2447
|
+
/** Whether the workflow, phase, or task cooperative gate is currently paused. */
|
|
2448
|
+
readonly paused: boolean;
|
|
2449
|
+
/**
|
|
2450
|
+
* Replace this running task's complete observable activity.
|
|
2451
|
+
*
|
|
2452
|
+
* @param input - The complete operations, progress, and constraints replacement
|
|
2453
|
+
* @returns The accepted frame, or a `TRANSITION` failure after ownership is lost or this attempt aborts
|
|
2454
|
+
*/
|
|
2455
|
+
report(input: TaskActivityInput): Result<TaskActivity, WorkflowError>;
|
|
2456
|
+
/**
|
|
2457
|
+
* Confirm liveness without replacing current activity.
|
|
2458
|
+
*
|
|
2459
|
+
* @returns `true` when committed, or `false` after ownership is lost or this attempt aborts
|
|
2460
|
+
*/
|
|
2461
|
+
pulse(): boolean;
|
|
2462
|
+
/**
|
|
2463
|
+
* Cooperatively park while any workflow, phase, or task gate is paused, or until cancelled.
|
|
2464
|
+
*
|
|
2465
|
+
* @returns A promise that resolves when every applicable gate is open or the signal aborts
|
|
2466
|
+
*/
|
|
2467
|
+
wait(): Promise<void>;
|
|
2224
2468
|
/** Every settled task's result across already-finished phases — the result tree, read-only. */
|
|
2225
2469
|
results(): readonly TaskResult[];
|
|
2226
2470
|
}
|
|
@@ -2235,8 +2479,8 @@ export declare interface TaskControllerInterface {
|
|
|
2235
2479
|
* its phase; `name` is the human label; `description` is optional prose. `run` is a
|
|
2236
2480
|
* PLAIN NAME — a key resolved ONCE at construction against a workflow-level
|
|
2237
2481
|
* {@link WorkflowFunctions} registry into a runtime {@link TaskInterface.handler}
|
|
2238
|
-
* carried on the live task.
|
|
2239
|
-
*
|
|
2482
|
+
* carried on the live task. An omitted `run` is the deliberate no-op form and completes
|
|
2483
|
+
* with JSON `null`; an unresolved present name remains inspectable but is not executable.
|
|
2240
2484
|
*/
|
|
2241
2485
|
export declare interface TaskDefinition {
|
|
2242
2486
|
readonly id: string;
|
|
@@ -2254,11 +2498,10 @@ export declare interface TaskDefinition {
|
|
|
2254
2498
|
readonly retries?: number;
|
|
2255
2499
|
/**
|
|
2256
2500
|
* @remarks
|
|
2257
|
-
* The per-attempt deadline in milliseconds
|
|
2258
|
-
*
|
|
2259
|
-
*
|
|
2260
|
-
*
|
|
2261
|
-
* reliability config; only the resolved handler itself is runtime-only.
|
|
2501
|
+
* The workflow-owned per-attempt deadline in milliseconds, an integer from `0` through
|
|
2502
|
+
* `MAX_TIMER_MS`. Zero or omission means no deadline. PERSISTED in a {@link TaskSnapshot},
|
|
2503
|
+
* so `restoreWorkflow(snapshot, { functions })` resumes with the same reliability config;
|
|
2504
|
+
* only the resolved handler itself is runtime-only.
|
|
2262
2505
|
*/
|
|
2263
2506
|
readonly timeout?: number;
|
|
2264
2507
|
}
|
|
@@ -2286,7 +2529,8 @@ export declare function taskDefinitionToSnapshot(task: WorkflowDefinition['phase
|
|
|
2286
2529
|
* @remarks
|
|
2287
2530
|
* `start` fires when the task begins; `complete` when it finishes successfully
|
|
2288
2531
|
* (carrying its {@link TaskResult}); `fail` when it errors (carrying the result);
|
|
2289
|
-
* `
|
|
2532
|
+
* `pause` / `resume` when its runtime gate closes / opens; `skip` when it is
|
|
2533
|
+
* intentionally not executed; `stop` when it is ended early. A
|
|
2290
2534
|
* throwing listener is isolated by the emitter and routed to its `error` handler,
|
|
2291
2535
|
* not the domain surface (AGENTS §13). A `type` alias (AGENTS §4.5) so it satisfies
|
|
2292
2536
|
* `EventMap`.
|
|
@@ -2298,12 +2542,46 @@ export declare type TaskEventMap = {
|
|
|
2298
2542
|
readonly complete: readonly [result: TaskResult];
|
|
2299
2543
|
/** The task failed — its result. */
|
|
2300
2544
|
readonly fail: readonly [result: TaskResult];
|
|
2545
|
+
/** The task's runtime gate closed. */
|
|
2546
|
+
readonly pause: readonly [];
|
|
2547
|
+
/** The task's runtime gate opened. */
|
|
2548
|
+
readonly resume: readonly [];
|
|
2301
2549
|
/** The task was intentionally skipped. */
|
|
2302
2550
|
readonly skip: readonly [];
|
|
2303
2551
|
/** The task was permanently stopped. */
|
|
2304
2552
|
readonly stop: readonly [];
|
|
2553
|
+
/** A complete activity replacement was committed. */
|
|
2554
|
+
readonly report: readonly [activity: TaskActivity];
|
|
2555
|
+
/** The task confirmed liveness without replacing its current activity. */
|
|
2556
|
+
readonly pulse: readonly [activity: TaskActivity];
|
|
2557
|
+
/** No report or pulse was accepted during the effective silence window. */
|
|
2558
|
+
readonly silence: readonly [];
|
|
2305
2559
|
};
|
|
2306
2560
|
|
|
2561
|
+
/** A normalized JSON-safe task failure persisted without a stack or cause. */
|
|
2562
|
+
export declare interface TaskFailure {
|
|
2563
|
+
readonly origin: TaskFailureOrigin;
|
|
2564
|
+
readonly message: string;
|
|
2565
|
+
}
|
|
2566
|
+
|
|
2567
|
+
/**
|
|
2568
|
+
* The structured outcome of a task execution — its full lineage, its terminal
|
|
2569
|
+
* status, the moment it settled, and its boxed produced outcome.
|
|
2570
|
+
*
|
|
2571
|
+
* @remarks
|
|
2572
|
+
* Carries the complete lineage (`task` / `phase` / `workflow` contexts) so a result
|
|
2573
|
+
* is self-describing wherever it travels. `status` is the terminal state this
|
|
2574
|
+
* result records. `result` BOXES the produced outcome in a {@link Result}: it is
|
|
2575
|
+
* PRESENT exactly when `status` is `completed` (a {@link import('@orkestrel/contract').Success})
|
|
2576
|
+
* or `failed` (a {@link import('@orkestrel/contract').Failure}), and ABSENT when `status` is
|
|
2577
|
+
* `skipped` or `stopped` (terminal, but produced no outcome) — a pending/running
|
|
2578
|
+
* task has no result at all (a non-terminal status, per
|
|
2579
|
+
* {@link import('./helpers.js').isTerminalStatus}). This boxed `result` REPLACES separate
|
|
2580
|
+
* `value?` / `error?` fields: a success's payload is `result.value`, a failure's reason is `result.error`.
|
|
2581
|
+
* `timestamp` is when the result was created (ms since epoch).
|
|
2582
|
+
*/
|
|
2583
|
+
export declare type TaskFailureOrigin = 'handler' | 'timeout' | 'recovery';
|
|
2584
|
+
|
|
2307
2585
|
/** Initial {@link TaskEventMap} listeners — the reserved `on` option (AGENTS §8). */
|
|
2308
2586
|
export declare type TaskHooks = EmitterHooks<TaskEventMap>;
|
|
2309
2587
|
|
|
@@ -2318,7 +2596,7 @@ export declare type TaskHooks = EmitterHooks<TaskEventMap>;
|
|
|
2318
2596
|
*/
|
|
2319
2597
|
export declare interface TaskInput extends Partial<TaskContext> {
|
|
2320
2598
|
/** An open consumer bag — stored and snapshotted, never interpreted by the workflow. */
|
|
2321
|
-
readonly metadata?:
|
|
2599
|
+
readonly metadata?: JSONRecord;
|
|
2322
2600
|
}
|
|
2323
2601
|
|
|
2324
2602
|
/**
|
|
@@ -2337,13 +2615,15 @@ export declare interface TaskInput extends Partial<TaskContext> {
|
|
|
2337
2615
|
* {@link import('@orkestrel/contract').Failure}), `skip` (AGENTS §10 — intentionally not run),
|
|
2338
2616
|
* and `stop` (AGENTS §10 — ended early). Each is GUARDED: an illegal transition (e.g.
|
|
2339
2617
|
* completing a non-`running` task) throws a {@link import('./errors.js').WorkflowError}.
|
|
2340
|
-
* `
|
|
2618
|
+
* A leaf needs no override: `skipped` / `stopped` are explicit terminal statuses and
|
|
2619
|
+
* restore directly from {@link TaskSnapshot.status}.
|
|
2341
2620
|
* - **Result.** `result` is the recorded {@link TaskResult} once the task settled with an
|
|
2342
2621
|
* outcome (`completed` / `failed`), else `undefined` — the lineage-navigable leaf of the
|
|
2343
2622
|
* result tree.
|
|
2344
2623
|
* - **Observable (AGENTS §13).** The owned {@link emitter} ({@link TaskEventMap}) fires
|
|
2345
|
-
* `start` / `complete` / `fail` / `skip` / `stop` strictly AFTER
|
|
2346
|
-
* emitter isolates a listener throw and routes it to its `error`
|
|
2624
|
+
* `start` / `complete` / `fail` / `pause` / `resume` / `skip` / `stop` strictly AFTER
|
|
2625
|
+
* each state change; the emitter isolates a listener throw and routes it to its `error`
|
|
2626
|
+
* handler (the `error` option).
|
|
2347
2627
|
*/
|
|
2348
2628
|
export declare interface TaskInterface {
|
|
2349
2629
|
readonly emitter: EmitterInterface<TaskEventMap>;
|
|
@@ -2354,6 +2634,8 @@ export declare interface TaskInterface {
|
|
|
2354
2634
|
readonly phase: PhaseInterface;
|
|
2355
2635
|
readonly workflow: WorkflowInterface;
|
|
2356
2636
|
readonly status: TaskStatus;
|
|
2637
|
+
/** Total launches already consumed; zero while fresh and one-based after launch. */
|
|
2638
|
+
readonly attempts: number;
|
|
2357
2639
|
/** The recorded outcome once the task settled with one (`completed` / `failed`), else `undefined`. */
|
|
2358
2640
|
readonly result: TaskResult | undefined;
|
|
2359
2641
|
/**
|
|
@@ -2366,9 +2648,9 @@ export declare interface TaskInterface {
|
|
|
2366
2648
|
* The RESOLVED runtime handler — RUNTIME-ONLY, NEVER persisted in a {@link TaskSnapshot}.
|
|
2367
2649
|
* Resolved ONCE at construction (build, restore, or a live mint) by looking `run` up in the
|
|
2368
2650
|
* workflow-level {@link WorkflowOptions.functions} registry: `functions?.[run]` when `run`
|
|
2369
|
-
* is defined, else `undefined`.
|
|
2370
|
-
*
|
|
2371
|
-
*
|
|
2651
|
+
* is defined, else `undefined`. An omitted `run` is the deliberate no-op form. A present,
|
|
2652
|
+
* unresolved `run` remains visible on exact restore, but the runner rejects it before
|
|
2653
|
+
* dispatch instead of falsely completing named work.
|
|
2372
2654
|
*/
|
|
2373
2655
|
readonly handler: WorkflowFunction | undefined;
|
|
2374
2656
|
/**
|
|
@@ -2377,15 +2659,49 @@ export declare interface TaskInterface {
|
|
|
2377
2659
|
*/
|
|
2378
2660
|
readonly retries: number | undefined;
|
|
2379
2661
|
/**
|
|
2380
|
-
* The per-attempt deadline in milliseconds — PERSISTED
|
|
2381
|
-
* / {@link TaskSnapshot.timeout}).
|
|
2662
|
+
* The workflow-owned per-attempt deadline in milliseconds (`0..MAX_TIMER_MS`) — PERSISTED
|
|
2663
|
+
* (mirrors {@link TaskDefinition.timeout} / {@link TaskSnapshot.timeout}). Zero or
|
|
2664
|
+
* `undefined` means no deadline.
|
|
2382
2665
|
*/
|
|
2383
2666
|
readonly timeout: number | undefined;
|
|
2667
|
+
/** The last accepted reporter claim, absent while pending. */
|
|
2668
|
+
readonly activity: TaskActivity | undefined;
|
|
2669
|
+
/** The effective host-safe silence window (`1..MAX_TIMER_MS`), or `undefined` when disabled. */
|
|
2670
|
+
readonly silence: number | undefined;
|
|
2671
|
+
/** Whether no report or pulse was accepted during the current silence window. */
|
|
2672
|
+
readonly silent: boolean;
|
|
2673
|
+
/** Whether this task's cooperative execution gate is paused. */
|
|
2674
|
+
readonly paused: boolean;
|
|
2675
|
+
/** This task's own cancellation signal; running/pending {@link stop} or {@link skip} fires it. */
|
|
2676
|
+
readonly signal: AbortSignal;
|
|
2384
2677
|
start(): void;
|
|
2385
|
-
complete(value:
|
|
2386
|
-
fail(error:
|
|
2678
|
+
complete(value: JSONValue): void;
|
|
2679
|
+
fail(error: TaskFailure): void;
|
|
2387
2680
|
skip(): void;
|
|
2388
2681
|
stop(): void;
|
|
2682
|
+
/**
|
|
2683
|
+
* Replace the complete observable activity of this running task.
|
|
2684
|
+
*
|
|
2685
|
+
* @param input - The complete operations, progress, and constraints replacement
|
|
2686
|
+
* @returns The accepted immutable frame; `MUTATION` for invalid input or `TRANSITION` when not running
|
|
2687
|
+
*/
|
|
2688
|
+
report(input: TaskActivityInput): Result<TaskActivity, WorkflowError>;
|
|
2689
|
+
/**
|
|
2690
|
+
* Confirm liveness without replacing the current operations, progress, or constraints.
|
|
2691
|
+
*
|
|
2692
|
+
* @returns `true` when committed, or `false` when the task is not running
|
|
2693
|
+
*/
|
|
2694
|
+
pulse(): boolean;
|
|
2695
|
+
/** Suspend this task's cooperative gate while pending or running; idempotent. */
|
|
2696
|
+
pause(): void;
|
|
2697
|
+
/** Continue this task's cooperative gate; idempotent. */
|
|
2698
|
+
resume(): void;
|
|
2699
|
+
/**
|
|
2700
|
+
* Park until this task is not paused.
|
|
2701
|
+
*
|
|
2702
|
+
* @returns A promise that resolves once the task gate is released
|
|
2703
|
+
*/
|
|
2704
|
+
wait(): Promise<void>;
|
|
2389
2705
|
/**
|
|
2390
2706
|
* Apply a validated declarative patch to SELF (`name` / `description`).
|
|
2391
2707
|
*
|
|
@@ -2514,6 +2830,19 @@ export declare interface TaskManagerInterface {
|
|
|
2514
2830
|
tasks(): readonly TaskInterface[];
|
|
2515
2831
|
}
|
|
2516
2832
|
|
|
2833
|
+
/**
|
|
2834
|
+
* One operation claimed active when a running task's complete frame was accepted.
|
|
2835
|
+
*
|
|
2836
|
+
* @remarks
|
|
2837
|
+
* `id` is stable within one complete activity report, `name` is the human-readable label,
|
|
2838
|
+
* and `started` is a finite non-negative reporter timestamp.
|
|
2839
|
+
*/
|
|
2840
|
+
export declare interface TaskOperation {
|
|
2841
|
+
readonly id: string;
|
|
2842
|
+
readonly name: string;
|
|
2843
|
+
readonly started: number;
|
|
2844
|
+
}
|
|
2845
|
+
|
|
2517
2846
|
/**
|
|
2518
2847
|
* The runtime options for a {@link TaskInterface} — the construction bag the live
|
|
2519
2848
|
* leaf state machine (W-b) carries that the W-a {@link TaskDefinition} did not.
|
|
@@ -2531,32 +2860,31 @@ export declare interface TaskOptions {
|
|
|
2531
2860
|
/** The emitter's listener-error handler (AGENTS §13) — a listener throw routes here, not to a domain event. */
|
|
2532
2861
|
readonly error?: EmitterErrorHandler;
|
|
2533
2862
|
/** An open consumer bag — stored and snapshotted, never interpreted by the workflow. */
|
|
2534
|
-
readonly metadata?:
|
|
2863
|
+
readonly metadata?: JSONRecord;
|
|
2864
|
+
/** Runtime-only silence window; non-positive, non-finite, or over-`MAX_TIMER_MS` disables inheritance. */
|
|
2865
|
+
readonly silence?: number;
|
|
2535
2866
|
}
|
|
2536
2867
|
|
|
2537
2868
|
/**
|
|
2538
|
-
* The
|
|
2539
|
-
* status, the moment it settled, and its boxed produced outcome.
|
|
2869
|
+
* The aggregate progress most recently reported by a running task.
|
|
2540
2870
|
*
|
|
2541
2871
|
* @remarks
|
|
2542
|
-
*
|
|
2543
|
-
* is
|
|
2544
|
-
* result records. `result` BOXES the produced outcome in a {@link Result}: it is
|
|
2545
|
-
* PRESENT exactly when `status` is `completed` (a {@link import('@orkestrel/contract').Success})
|
|
2546
|
-
* or `failed` (a {@link import('@orkestrel/contract').Failure}), and ABSENT when `status` is
|
|
2547
|
-
* `skipped` or `stopped` (terminal, but produced no outcome) — a pending/running
|
|
2548
|
-
* task has no result at all (a non-terminal status, per
|
|
2549
|
-
* {@link import('./helpers.js').isTerminalStatus}). This boxed `result` REPLACES separate
|
|
2550
|
-
* `value?` / `error?` fields: a success's payload is `result.value`, a failure's reason is `result.error`.
|
|
2551
|
-
* `timestamp` is when the result was created (ms since epoch).
|
|
2872
|
+
* `current` and an optional `total` are finite non-negative numbers; when `total` is present
|
|
2873
|
+
* it is at least `current`. `unit` is optional observer-facing text.
|
|
2552
2874
|
*/
|
|
2875
|
+
export declare interface TaskProgress {
|
|
2876
|
+
readonly current: number;
|
|
2877
|
+
readonly total?: number;
|
|
2878
|
+
readonly unit?: string;
|
|
2879
|
+
}
|
|
2880
|
+
|
|
2553
2881
|
export declare interface TaskResult {
|
|
2554
2882
|
readonly task: TaskContext;
|
|
2555
2883
|
readonly phase: PhaseContext;
|
|
2556
2884
|
readonly workflow: WorkflowContext;
|
|
2557
2885
|
readonly status: TaskStatus;
|
|
2558
2886
|
/** The boxed outcome — present for `completed` (Success) / `failed` (Failure), absent otherwise. */
|
|
2559
|
-
readonly result?: Result<
|
|
2887
|
+
readonly result?: Result<JSONValue, TaskFailure>;
|
|
2560
2888
|
readonly timestamp: number;
|
|
2561
2889
|
}
|
|
2562
2890
|
|
|
@@ -2595,13 +2923,17 @@ export declare interface TaskSnapshot {
|
|
|
2595
2923
|
readonly description?: string;
|
|
2596
2924
|
readonly status: TaskStatus;
|
|
2597
2925
|
readonly result?: TaskResult;
|
|
2598
|
-
readonly metadata:
|
|
2926
|
+
readonly metadata: JSONRecord;
|
|
2927
|
+
/** Total launches already consumed; zero while fresh and never reset by recovery. */
|
|
2928
|
+
readonly attempts: number;
|
|
2599
2929
|
/** The behavior reference — a registry key resolved against {@link WorkflowFunctions} on restore/build. */
|
|
2600
2930
|
readonly run?: string;
|
|
2601
2931
|
/** Extra attempts after the first on failure (a non-negative integer); overrides the phase Runner default. */
|
|
2602
2932
|
readonly retries?: number;
|
|
2603
|
-
/**
|
|
2933
|
+
/** Workflow-owned per-attempt deadline (`0..MAX_TIMER_MS`); zero or omission means disabled. */
|
|
2604
2934
|
readonly timeout?: number;
|
|
2935
|
+
/** Pending omits activity; running/completed/failed require it; skipped/stopped may retain it. */
|
|
2936
|
+
readonly activity?: TaskActivity;
|
|
2605
2937
|
}
|
|
2606
2938
|
|
|
2607
2939
|
/**
|
|
@@ -2694,24 +3026,26 @@ export declare type UnitOutcome<TResult> = {
|
|
|
2694
3026
|
* - **Construction.** Built from a {@link WorkflowSnapshot} (the unified input —
|
|
2695
3027
|
* {@link import('./factories.js').createWorkflow} seeds an initial snapshot from a
|
|
2696
3028
|
* {@link import('./types.js').WorkflowDefinition}, {@link import('./factories.js').restoreWorkflow}
|
|
2697
|
-
* passes a persisted one). Each child {@link Phase} is wired to escalate to
|
|
3029
|
+
* passes a persisted one). Each child {@link Phase} is wired to escalate to `#recompute`.
|
|
2698
3030
|
* - **Derived status.** `status` is `#override` when forced, else
|
|
2699
3031
|
* {@link deriveWorkflowStatus} over the live phases' statuses feeding `bail`. `failed` is
|
|
2700
3032
|
* reachable ONLY under `bail: true` (a single failed task halts the workflow); under
|
|
2701
|
-
* `bail: false` a failed phase folds into `completed`.
|
|
3033
|
+
* `bail: false` a failed phase folds into `completed`. `#recompute` diffs on each phase
|
|
2702
3034
|
* change; a CHANGE emits.
|
|
2703
|
-
* - **Override (AGENTS §10).** `skip` / `stop` FORCE the status;
|
|
2704
|
-
*
|
|
2705
|
-
*
|
|
3035
|
+
* - **Override (AGENTS §10).** `skip` / `stop` FORCE the status; an executed task-free pending tree
|
|
3036
|
+
* may also be force-completed vacuously. The override is PERSISTED in the snapshot's own
|
|
3037
|
+
* `override` field and restored DIRECTLY (no divergence guess). The snapshot also persists
|
|
3038
|
+
* `bail`, so a restore re-derives status identically without a silent policy default.
|
|
2706
3039
|
* - **Result tree.** `results()` flattens every phase's `results()` ({@link collectResults}) — the
|
|
2707
3040
|
* workflow tier; `phase(id)` + each `phase.task(id)` navigate DOWN, a task's `phase` / `workflow`
|
|
2708
3041
|
* navigate UP.
|
|
2709
3042
|
* - **Snapshot.** `snapshot()` serializes the whole live tree to a {@link WorkflowSnapshot} (pure
|
|
2710
3043
|
* JSON); {@link import('./factories.js').restoreWorkflow} rebuilds an equivalent live tree.
|
|
2711
3044
|
* - **Observable (AGENTS §13).** The owned {@link emitter} ({@link WorkflowEventMap}) fires
|
|
2712
|
-
* `start` / `complete` / `fail` / `
|
|
2713
|
-
*
|
|
2714
|
-
* the failing task's
|
|
3045
|
+
* `start` / `complete` / `fail` / `pause` / `resume` / `skip` / `stop` after the
|
|
3046
|
+
* corresponding status or runtime-gate change; the emitter isolates a listener throw and
|
|
3047
|
+
* routes it to its `error` handler (the `error` option); `fail` carries the failing task's
|
|
3048
|
+
* {@link TaskResult}.
|
|
2715
3049
|
* - **Structural API (AGENTS §7).** `add` / `remove` / `move` / `update` gate BEFORE
|
|
2716
3050
|
* delegating to {@link phases} (the manager gates the target's own existence/status/id/
|
|
2717
3051
|
* bounds), then emit the matching {@link WorkflowEventMap} event on success only. NATIVE,
|
|
@@ -2723,10 +3057,10 @@ export declare type UnitOutcome<TResult> = {
|
|
|
2723
3057
|
* naturally accepted.
|
|
2724
3058
|
* - **Runtime lifecycle (AGENTS §10).** `pause` / `resume` / `wait` gate execution at the runner's
|
|
2725
3059
|
* phase/task boundaries WITHOUT touching {@link status} — `paused` is runtime-only, never
|
|
2726
|
-
* persisted. `destroy` is a terminal teardown: it
|
|
2727
|
-
*
|
|
2728
|
-
*
|
|
2729
|
-
*
|
|
3060
|
+
* persisted. `destroy` is a terminal teardown: it `stop`s every non-terminal task and
|
|
3061
|
+
* phase (releasing their gates and liveness resources), aborts {@link signal}, forces the
|
|
3062
|
+
* workflow `stop` override when needed, releases its parked waiter, and marks
|
|
3063
|
+
* {@link destroyed} — all idempotent.
|
|
2730
3064
|
*/
|
|
2731
3065
|
export declare class Workflow implements WorkflowInterface {
|
|
2732
3066
|
#private;
|
|
@@ -2761,6 +3095,9 @@ export declare class Workflow implements WorkflowInterface {
|
|
|
2761
3095
|
/** Every {@link WorkflowStatus} value, frozen — the lifecycle vocabulary of a workflow. */
|
|
2762
3096
|
export declare const WORKFLOW_STATUSES: readonly WorkflowStatus[];
|
|
2763
3097
|
|
|
3098
|
+
/** A runner-owned durability boundary. */
|
|
3099
|
+
export declare type WorkflowCheckpoint = 'initial' | 'attempt' | 'settlement' | 'final';
|
|
3100
|
+
|
|
2764
3101
|
/**
|
|
2765
3102
|
* The ambient context of a workflow — the identity every level inherits.
|
|
2766
3103
|
*
|
|
@@ -2797,18 +3134,13 @@ export declare interface WorkflowDefinition {
|
|
|
2797
3134
|
}
|
|
2798
3135
|
|
|
2799
3136
|
/**
|
|
2800
|
-
* An error
|
|
3137
|
+
* An error raised by the workflow runtime.
|
|
2801
3138
|
*
|
|
2802
3139
|
* @remarks
|
|
2803
3140
|
* Carries a {@link WorkflowErrorCode} and an optional `context` bag naming the
|
|
2804
|
-
* offending node id / status.
|
|
3141
|
+
* offending node id / status. Raised for an illegal lifecycle transition
|
|
2805
3142
|
* (`TRANSITION`), a structurally invalid {@link import('./types.js').WorkflowSnapshot}
|
|
2806
|
-
*
|
|
2807
|
-
* cyclic nested-workflow dispatch (`DEPTH`), and a malformed workflow-authoring-tool args
|
|
2808
|
-
* blob (`TOOL`). `DEPTH` and `TOOL` are public type surface constructed by the
|
|
2809
|
-
* `@orkestrel/tool` package's workflow-tool / agent-function adapters; on that seam the
|
|
2810
|
-
* throw is ISOLATED by its `ToolManager` into the tool result's top-level `error`
|
|
2811
|
-
* (AGENTS §14 — the universal tool-handler contract).
|
|
3143
|
+
* boundary (`RESTORE`), or a refused structural/activity edit (`MUTATION`).
|
|
2812
3144
|
*/
|
|
2813
3145
|
export declare class WorkflowError extends Error {
|
|
2814
3146
|
readonly code: WorkflowErrorCode;
|
|
@@ -2826,21 +3158,6 @@ export declare class WorkflowError extends Error {
|
|
|
2826
3158
|
* the offending current status + requested transition in the error `context`.
|
|
2827
3159
|
* - `RESTORE` — a {@link import('./factories.js').restoreWorkflow} given a structurally
|
|
2828
3160
|
* invalid {@link WorkflowSnapshot} (a status outside the lifecycle vocabulary).
|
|
2829
|
-
* - `DEPTH` — a nested-workflow dispatch (W-c2) that a depth / cycle guard rejected:
|
|
2830
|
-
* running it would push the nested-workflow chain past a bounded max depth, OR its
|
|
2831
|
-
* target agent (or a workflow it would author) is already an ancestor of the current
|
|
2832
|
-
* run (a re-entry cycle). Public type surface consumed by the `@orkestrel/tool`
|
|
2833
|
-
* package's workflow-tool / agent-function adapters, which construct
|
|
2834
|
-
* {@link import('./errors.js').WorkflowError}s with this code (thrown, then ISOLATED
|
|
2835
|
-
* by that package's `ToolManager` into the tool result's `error`). The error `context`
|
|
2836
|
-
* names the offending agent / workflow id + the depth.
|
|
2837
|
-
* - `TOOL` — a workflow-authoring tool handler (in `@orkestrel/tool`) was handed a
|
|
2838
|
-
* MALFORMED / over-constraint authored args blob (e.g. an empty `id`, `concurrency: 0`)
|
|
2839
|
-
* that {@link import('./factories.js').createWorkflowContract} rejected, so no workflow
|
|
2840
|
-
* ran. Public type surface: `@orkestrel/tool` constructs this code and THROWS it
|
|
2841
|
-
* (rather than returning a failure result); its `ToolManager` ISOLATES the throw into
|
|
2842
|
-
* the canonical tool result's top-level `error` (AGENTS §14 — the universal
|
|
2843
|
-
* tool-handler contract); the error `context` names the wrapped workflow id.
|
|
2844
3161
|
* - `MUTATION` — a GATED structural or patch edit was refused: a duplicate id on
|
|
2845
3162
|
* `append`/`add`, a target that does not exist or is not `pending`, an out-of-bounds
|
|
2846
3163
|
* `index`, a patch that failed shaper validation, or a live structural edit refused by
|
|
@@ -2854,7 +3171,7 @@ export declare class WorkflowError extends Error {
|
|
|
2854
3171
|
* guard (both genuine programmer-error paths, AGENTS §12). The error `context` names
|
|
2855
3172
|
* the offending id / index / status.
|
|
2856
3173
|
*/
|
|
2857
|
-
export declare type WorkflowErrorCode = 'TRANSITION' | 'RESTORE' | '
|
|
3174
|
+
export declare type WorkflowErrorCode = 'TRANSITION' | 'RESTORE' | 'MUTATION';
|
|
2858
3175
|
|
|
2859
3176
|
/**
|
|
2860
3177
|
* The push observation surface (AGENTS §13) of the workflow entity (W-b) — the
|
|
@@ -2864,8 +3181,10 @@ export declare type WorkflowErrorCode = 'TRANSITION' | 'RESTORE' | 'DEPTH' | 'TO
|
|
|
2864
3181
|
* @remarks
|
|
2865
3182
|
* Present-tense events with arg tuples. `start` fires when the workflow begins;
|
|
2866
3183
|
* `complete` when every phase settled successfully; `fail` when a phase failed
|
|
2867
|
-
* under `bail` (carrying the failing {@link TaskResult}); `
|
|
2868
|
-
*
|
|
3184
|
+
* under `bail` (carrying the failing {@link TaskResult}); `pause` / `resume` when its
|
|
3185
|
+
* runtime gate closes / opens; `skip` when the workflow was intentionally skipped;
|
|
3186
|
+
* `stop` when it was permanently ended. `add` / `remove`
|
|
3187
|
+
* / `move` / `update` fire on a successful
|
|
2869
3188
|
* structural or patch edit through {@link WorkflowInterface.add} / `remove` / `move` /
|
|
2870
3189
|
* `update` (AGENTS §7) — never on a refused/gated one. A throwing listener never
|
|
2871
3190
|
* reaches the domain surface — the emitter isolates it and routes it to its OWN
|
|
@@ -2880,6 +3199,12 @@ export declare type WorkflowEventMap = {
|
|
|
2880
3199
|
readonly complete: readonly [];
|
|
2881
3200
|
/** A phase failed under `bail` — the failing task's result. */
|
|
2882
3201
|
readonly fail: readonly [result: TaskResult];
|
|
3202
|
+
/** The workflow's runtime gate closed. */
|
|
3203
|
+
readonly pause: readonly [];
|
|
3204
|
+
/** The workflow's runtime gate opened. */
|
|
3205
|
+
readonly resume: readonly [];
|
|
3206
|
+
/** The workflow was intentionally skipped. */
|
|
3207
|
+
readonly skip: readonly [];
|
|
2883
3208
|
/** The workflow was permanently stopped. */
|
|
2884
3209
|
readonly stop: readonly [];
|
|
2885
3210
|
/** A phase was inserted — the inserted phase + its final index. */
|
|
@@ -2892,6 +3217,15 @@ export declare type WorkflowEventMap = {
|
|
|
2892
3217
|
readonly update: readonly [phase: PhaseInterface];
|
|
2893
3218
|
};
|
|
2894
3219
|
|
|
3220
|
+
/** A normalized persistence failure surfaced as workflow result data. */
|
|
3221
|
+
export declare interface WorkflowFault {
|
|
3222
|
+
readonly origin: 'persistence';
|
|
3223
|
+
readonly checkpoint: WorkflowCheckpoint;
|
|
3224
|
+
readonly message: string;
|
|
3225
|
+
readonly task?: string;
|
|
3226
|
+
readonly attempt?: number;
|
|
3227
|
+
}
|
|
3228
|
+
|
|
2895
3229
|
/**
|
|
2896
3230
|
* A registered workflow function — the behavior a `function`-form
|
|
2897
3231
|
* {@link TaskDefinition} runs, resolved BY NAME through the {@link WorkflowFunctions}
|
|
@@ -2906,7 +3240,7 @@ export declare type WorkflowEventMap = {
|
|
|
2906
3240
|
* should honour `controller.signal` (a workflow-level abort / timeout / budget, or — under
|
|
2907
3241
|
* `bail: true` — a sibling's failure, fires it) so a cancel stops it promptly.
|
|
2908
3242
|
*/
|
|
2909
|
-
export declare type WorkflowFunction = (controller: TaskControllerInterface) => Promise<
|
|
3243
|
+
export declare type WorkflowFunction = (controller: TaskControllerInterface) => Promise<JSONValue> | JSONValue;
|
|
2910
3244
|
|
|
2911
3245
|
/**
|
|
2912
3246
|
* The `function`-task behavior registry — workflow function names mapped to their
|
|
@@ -2914,9 +3248,10 @@ export declare type WorkflowFunction = (controller: TaskControllerInterface) =>
|
|
|
2914
3248
|
*
|
|
2915
3249
|
* @remarks
|
|
2916
3250
|
* A live {@link TaskInterface} resolves its `run` name against this registry ONCE at
|
|
2917
|
-
* construction into its {@link TaskInterface.handler}.
|
|
2918
|
-
*
|
|
2919
|
-
* plain record (not a manager) — the
|
|
3251
|
+
* construction into its {@link TaskInterface.handler}. An omitted `run` is the deliberate
|
|
3252
|
+
* no-op case. A present name absent from the registry remains inspectable but makes the tree
|
|
3253
|
+
* non-drivable until restored with a matching handler. A plain record (not a manager) — the
|
|
3254
|
+
* registry is a lookup, with no lifecycle of its own.
|
|
2920
3255
|
*/
|
|
2921
3256
|
export declare type WorkflowFunctions = Readonly<Record<string, WorkflowFunction>>;
|
|
2922
3257
|
|
|
@@ -2940,14 +3275,15 @@ export declare type WorkflowInput = Partial<WorkflowContext>;
|
|
|
2940
3275
|
* - **Children.** `phases` is the lean {@link PhaseManagerInterface} (AGENTS §9);
|
|
2941
3276
|
* `phase(id)` / `phases().phases()` read in positional order. `results` collects ALL
|
|
2942
3277
|
* tasks' results across every phase (the workflow tier of the result tree).
|
|
2943
|
-
* - **Override.** `skip` / `stop` (AGENTS §10) FORCE the workflow's status;
|
|
2944
|
-
* survives a snapshot.
|
|
3278
|
+
* - **Override.** `skip` / `stop` (AGENTS §10) FORCE the workflow's status; `complete`
|
|
3279
|
+
* may force only a task-free, otherwise-pending tree. The override survives a snapshot.
|
|
2945
3280
|
* - **Snapshot.** `snapshot()` serializes the whole live tree to a {@link WorkflowSnapshot}
|
|
2946
3281
|
* (pure JSON — structure + each node's status + recorded results + positional order);
|
|
2947
3282
|
* {@link restoreWorkflow} rebuilds an equivalent live tree.
|
|
2948
3283
|
* - **Observable (AGENTS §13).** The owned {@link emitter} ({@link WorkflowEventMap}) fires
|
|
2949
|
-
* `start` / `complete` / `fail` / `
|
|
2950
|
-
* listener throw and routes it to
|
|
3284
|
+
* `start` / `complete` / `fail` / `pause` / `resume` / `stop` after the corresponding
|
|
3285
|
+
* status or runtime-gate change; the emitter isolates a listener throw and routes it to
|
|
3286
|
+
* its `error` handler (the `error` option).
|
|
2951
3287
|
*/
|
|
2952
3288
|
export declare interface WorkflowInterface {
|
|
2953
3289
|
readonly emitter: EmitterInterface<WorkflowEventMap>;
|
|
@@ -2997,9 +3333,9 @@ export declare interface WorkflowInterface {
|
|
|
2997
3333
|
* FORCE this workflow to `completed` (AGENTS §10), overriding the derived value.
|
|
2998
3334
|
*
|
|
2999
3335
|
* @remarks
|
|
3000
|
-
* A NO-OP unless `status` is `pending`
|
|
3001
|
-
*
|
|
3002
|
-
*
|
|
3336
|
+
* A NO-OP unless `status` is `pending` and the tree is genuinely vacuous: zero phases or
|
|
3337
|
+
* every phase contains zero tasks. Its ONLY legitimate use is settling an executed no-op
|
|
3338
|
+
* tree. It never overrides pending work or any started/terminal state.
|
|
3003
3339
|
*/
|
|
3004
3340
|
complete(): void;
|
|
3005
3341
|
/**
|
|
@@ -3033,16 +3369,15 @@ export declare interface WorkflowInterface {
|
|
|
3033
3369
|
*/
|
|
3034
3370
|
resume(): void;
|
|
3035
3371
|
/**
|
|
3036
|
-
* Tear this workflow down (AGENTS §10) —
|
|
3037
|
-
*
|
|
3038
|
-
*
|
|
3039
|
-
*
|
|
3040
|
-
* {@link destroyed}; idempotent.
|
|
3372
|
+
* Tear this workflow down (AGENTS §10) — an atomic TERMINAL teardown: mark
|
|
3373
|
+
* {@link destroyed}, pin non-terminal workflow/phase overrides to `stopped`, stop every
|
|
3374
|
+
* non-terminal task, release gates and liveness resources, abort {@link signal}, then
|
|
3375
|
+
* destroy task, phase, and workflow emitters in ownership order; idempotent.
|
|
3041
3376
|
*
|
|
3042
3377
|
* @remarks
|
|
3043
|
-
*
|
|
3044
|
-
*
|
|
3045
|
-
*
|
|
3378
|
+
* {@link destroyed} is set before final events, so reentrant mutation is refused and a
|
|
3379
|
+
* recursive `destroy` is a no-op. Already-terminal genuine completed/failed state is
|
|
3380
|
+
* preserved, and state/snapshots remain inspectable after emitter resources are destroyed.
|
|
3046
3381
|
*
|
|
3047
3382
|
* @example
|
|
3048
3383
|
* ```ts
|
|
@@ -3149,12 +3484,11 @@ export declare interface WorkflowInterface {
|
|
|
3149
3484
|
* `functions` registry in) and stores it under `definition.id` — an already-present id
|
|
3150
3485
|
* OVERWRITES (last write wins). `count` is the map size, `workflow(id)` looks one up,
|
|
3151
3486
|
* `workflows()` lists them in insertion order.
|
|
3152
|
-
* - **Durable open / save.** `open(id)` returns an already-registered workflow directly;
|
|
3153
|
-
*
|
|
3154
|
-
*
|
|
3155
|
-
*
|
|
3156
|
-
*
|
|
3157
|
-
* unknown id.
|
|
3487
|
+
* - **Durable open / save.** `open(id)` returns an already-registered workflow directly; same-id
|
|
3488
|
+
* misses share one hydration. A concurrent `add` wins, while `remove` / `clear` invalidate
|
|
3489
|
+
* earlier reads; wrong-key payloads reject with `RESTORE`. `save(id)` captures a registered
|
|
3490
|
+
* workflow's snapshot at invocation and serializes same-id writes without coupling other ids.
|
|
3491
|
+
* Both remain lenient without a store or registered id.
|
|
3158
3492
|
* - **Removal.** `remove` drops one by id, or a batch (§9.2, array overload FIRST) — `true` when
|
|
3159
3493
|
* any was removed. `clear` empties the registry.
|
|
3160
3494
|
* - **No active pointer.** Unlike its `ConversationManager` / `WorkspaceManager` twins, there is
|
|
@@ -3204,10 +3538,17 @@ export declare class WorkflowManager implements WorkflowManagerInterface {
|
|
|
3204
3538
|
* `workflows()` lists them in insertion order.
|
|
3205
3539
|
* - **Durable open / save (the optional `store` seam).** When a {@link WorkflowStoreInterface}
|
|
3206
3540
|
* is supplied (the `store` option), `open(id)` resolves an already-registered workflow
|
|
3207
|
-
* directly (no store hit);
|
|
3541
|
+
* directly (no store hit); same-id registry misses share one in-flight hydration. On a MISS
|
|
3542
|
+
* it HYDRATES one from `store.get(id)` through
|
|
3208
3543
|
* {@link import('./factories.js').restoreWorkflow} — flowing this manager's `functions`
|
|
3209
|
-
* registry in so the rehydrated tree is RUNNABLE — registers it, and returns it.
|
|
3210
|
-
*
|
|
3544
|
+
* registry in so the rehydrated tree is RUNNABLE — registers it, and returns it. Registry
|
|
3545
|
+
* mutation wins over an earlier pending hydration: `add` supplies the live result, while
|
|
3546
|
+
* `remove` (even for an absent id) and `clear` invalidate the earlier read. Missed and failed
|
|
3547
|
+
* reads leave no stale in-flight entry, and a payload whose own id differs from the requested
|
|
3548
|
+
* key rejects with `RESTORE` instead of registering under either id. `save(id)` captures a
|
|
3549
|
+
* registered workflow's {@link WorkflowInterface.snapshot} at invocation, then PERSISTS it.
|
|
3550
|
+
* Same-id writes run serially in invocation order; different ids remain independent, and an
|
|
3551
|
+
* earlier rejection reaches its caller without preventing a later queued write. Both are
|
|
3211
3552
|
* LENIENT without a store — `open` resolves only registered ids, `save` is a no-op
|
|
3212
3553
|
* (`false`) — never a throw. The EXACT analogue of
|
|
3213
3554
|
* `ConversationManagerInterface.open` / `.save` and `WorkspaceManagerInterface.open` /
|
|
@@ -3221,7 +3562,7 @@ export declare class WorkflowManager implements WorkflowManagerInterface {
|
|
|
3221
3562
|
*
|
|
3222
3563
|
* @example
|
|
3223
3564
|
* ```ts
|
|
3224
|
-
* import { createWorkflowManager } from '@
|
|
3565
|
+
* import { createWorkflowManager } from '@orkestrel/workflow'
|
|
3225
3566
|
*
|
|
3226
3567
|
* const manager = createWorkflowManager({
|
|
3227
3568
|
* functions: { compile: async (controller) => `built ${controller.task.id}` },
|
|
@@ -3255,11 +3596,17 @@ export declare interface WorkflowManagerInterface {
|
|
|
3255
3596
|
*
|
|
3256
3597
|
* @remarks
|
|
3257
3598
|
* - If `id` is ALREADY registered, it is returned directly — no store hit.
|
|
3258
|
-
* -
|
|
3599
|
+
* - Same-id registry misses share one in-flight `store.get(id)` and resolve to the same live
|
|
3600
|
+
* object. On a HIT the snapshot is
|
|
3259
3601
|
* rehydrated into a fresh {@link WorkflowInterface} via
|
|
3260
3602
|
* {@link import('./factories.js').restoreWorkflow}, flowing this manager's `functions`
|
|
3261
3603
|
* registry in (so the rehydrated tree carries real resolved `handler`s and can RESUME
|
|
3262
|
-
* real work), registers it, and returns it.
|
|
3604
|
+
* real work), registers it, and returns it. A payload whose own id differs from `id` rejects
|
|
3605
|
+
* with a normalized `RESTORE` error carrying the requested and payload ids.
|
|
3606
|
+
* - Registry mutation after the store read starts has precedence: `add(definition)` for the
|
|
3607
|
+
* same id wins and becomes every pending caller's result; `remove(id)` invalidates that read
|
|
3608
|
+
* even when the id was absent; `clear()` invalidates every earlier read. A miss or rejection
|
|
3609
|
+
* clears the in-flight entry so a later call retries.
|
|
3263
3610
|
* - Else (no store, or a store MISS) ⇒ `undefined` (lenient — no throw).
|
|
3264
3611
|
*
|
|
3265
3612
|
* @param id - The workflow id to open
|
|
@@ -3271,9 +3618,10 @@ export declare interface WorkflowManagerInterface {
|
|
|
3271
3618
|
* {@link WorkflowStoreInterface} (`store`).
|
|
3272
3619
|
*
|
|
3273
3620
|
* @remarks
|
|
3274
|
-
*
|
|
3275
|
-
*
|
|
3276
|
-
*
|
|
3621
|
+
* When a `store` is set AND `id` is registered, the snapshot is captured synchronously at
|
|
3622
|
+
* invocation. Same-id `store.set` calls are serialized in invocation order; different ids are
|
|
3623
|
+
* independent. A rejected write reaches that caller unchanged but does not poison a later
|
|
3624
|
+
* queued write. Otherwise (no store, OR an unknown id) it is a NO-OP returning `false`.
|
|
3277
3625
|
*
|
|
3278
3626
|
* @param id - The id of the registered workflow to persist
|
|
3279
3627
|
* @returns `true` when the snapshot was persisted; `false` when no store / unknown id
|
|
@@ -3298,9 +3646,8 @@ export declare interface WorkflowManagerInterface {
|
|
|
3298
3646
|
* every {@link import('./factories.js').createWorkflow} ({@link WorkflowManagerInterface.add})
|
|
3299
3647
|
* and every {@link import('./factories.js').restoreWorkflow}
|
|
3300
3648
|
* ({@link WorkflowManagerInterface.open}'s hydration path) the manager performs — so a
|
|
3301
|
-
* hydrated workflow carries real resolved `handler`s and is RUNNABLE
|
|
3302
|
-
*
|
|
3303
|
-
* rule — it auto-completes if driven).
|
|
3649
|
+
* hydrated workflow carries real resolved `handler`s and is RUNNABLE. Omitted ⇒ named work
|
|
3650
|
+
* remains inspectable but cannot be driven; omitted-`run` tasks remain deliberate no-ops.
|
|
3304
3651
|
*/
|
|
3305
3652
|
export declare interface WorkflowManagerOptions {
|
|
3306
3653
|
/**
|
|
@@ -3316,7 +3663,7 @@ export declare interface WorkflowManagerOptions {
|
|
|
3316
3663
|
* (`add`, via {@link import('./factories.js').createWorkflow}) or hydrates (`open`'s
|
|
3317
3664
|
* registry-miss path, via {@link import('./factories.js').restoreWorkflow}) — so a
|
|
3318
3665
|
* hydrated workflow is RUNNABLE, its tasks carrying real resolved `handler`s. Omitted ⇒
|
|
3319
|
-
*
|
|
3666
|
+
* named tasks remain inspectable but execution rejects them.
|
|
3320
3667
|
*/
|
|
3321
3668
|
readonly functions?: WorkflowFunctions;
|
|
3322
3669
|
}
|
|
@@ -3354,12 +3701,66 @@ export declare interface WorkflowOptions {
|
|
|
3354
3701
|
* fresh build ({@link import('./factories.js').createWorkflow}) and a restore
|
|
3355
3702
|
* ({@link import('./factories.js').restoreWorkflow}) both consume, and the same shape a
|
|
3356
3703
|
* live {@link WorkflowInterface.add} / {@link PhaseInterface.add} mint resolves a newly
|
|
3357
|
-
* minted task against.
|
|
3358
|
-
*
|
|
3359
|
-
*
|
|
3360
|
-
* Omitted ⇒ an empty registry
|
|
3704
|
+
* minted task against. An omitted `run` resolves to no handler and is the deliberate
|
|
3705
|
+
* no-op form. A present name absent from `functions` also has no handler so exact restore
|
|
3706
|
+
* remains inspectable, but {@link WorkflowRunnerInterface.execute} rejects that tree.
|
|
3707
|
+
* Omitted ⇒ an empty registry; only tasks that also omit `run` are executable no-ops.
|
|
3361
3708
|
*/
|
|
3362
3709
|
readonly functions?: WorkflowFunctions;
|
|
3710
|
+
/** Runtime-only default silence; non-positive, non-finite, or over-`MAX_TIMER_MS` disables it. */
|
|
3711
|
+
readonly silence?: number;
|
|
3712
|
+
}
|
|
3713
|
+
|
|
3714
|
+
/**
|
|
3715
|
+
* Advanced run-local snapshot persistence with one writer and one coalesced latest obligation.
|
|
3716
|
+
*
|
|
3717
|
+
* @remarks
|
|
3718
|
+
* Normally composed by `WorkflowRunner.execute({ store })`; exported for hosts that need to
|
|
3719
|
+
* coordinate the same required boundaries around their own runner integration.
|
|
3720
|
+
*/
|
|
3721
|
+
export declare class WorkflowPersistence implements WorkflowPersistenceInterface {
|
|
3722
|
+
#private;
|
|
3723
|
+
constructor(workflow: WorkflowInterface, store: WorkflowStoreInterface);
|
|
3724
|
+
get fault(): WorkflowFault | undefined;
|
|
3725
|
+
/**
|
|
3726
|
+
* Persist every change through this required boundary.
|
|
3727
|
+
*
|
|
3728
|
+
* @param checkpoint - The boundary being made durable
|
|
3729
|
+
* @param task - The task owning an attempt or settlement
|
|
3730
|
+
* @param attempt - The persisted attempt number
|
|
3731
|
+
* @returns Whether the latest state reached the store
|
|
3732
|
+
*/
|
|
3733
|
+
checkpoint(checkpoint: WorkflowCheckpoint, task?: TaskInterface, attempt?: number): Promise<boolean>;
|
|
3734
|
+
/**
|
|
3735
|
+
* Stop observing the live tree and persist its final state.
|
|
3736
|
+
*
|
|
3737
|
+
* @returns Whether the final snapshot reached the store
|
|
3738
|
+
*/
|
|
3739
|
+
finalize(): Promise<boolean>;
|
|
3740
|
+
/** Stop observing the live tree. */
|
|
3741
|
+
detach(): void;
|
|
3742
|
+
}
|
|
3743
|
+
|
|
3744
|
+
/**
|
|
3745
|
+
* The advanced run-local durability coordinator normally composed by
|
|
3746
|
+
* {@link WorkflowRunnerInterface.execute} when `store` is supplied.
|
|
3747
|
+
*/
|
|
3748
|
+
export declare interface WorkflowPersistenceInterface {
|
|
3749
|
+
/** The first required checkpoint failure, if one occurred. */
|
|
3750
|
+
readonly fault: WorkflowFault | undefined;
|
|
3751
|
+
/**
|
|
3752
|
+
* Make the latest state durable at one required boundary.
|
|
3753
|
+
*
|
|
3754
|
+
* @param checkpoint - The required durability boundary
|
|
3755
|
+
* @param task - The task owning an attempt or settlement
|
|
3756
|
+
* @param attempt - The persisted one-based attempt number
|
|
3757
|
+
* @returns Whether the latest live state reached the store
|
|
3758
|
+
*/
|
|
3759
|
+
checkpoint(checkpoint: WorkflowCheckpoint, task?: TaskInterface, attempt?: number): Promise<boolean>;
|
|
3760
|
+
/** Detach observers and make the final live state durable. */
|
|
3761
|
+
finalize(): Promise<boolean>;
|
|
3762
|
+
/** Stop observing the live workflow tree; idempotent. */
|
|
3763
|
+
detach(): void;
|
|
3363
3764
|
}
|
|
3364
3765
|
|
|
3365
3766
|
/**
|
|
@@ -3376,11 +3777,17 @@ export declare interface WorkflowOptions {
|
|
|
3376
3777
|
* settled task across all phases, in positional order — the same array `workflow.results()`
|
|
3377
3778
|
* yields). Returning the live `workflow` (not just a snapshot) keeps the entity tree the
|
|
3378
3779
|
* source of truth — the runner adds only the convenience `status` / `results` projections.
|
|
3780
|
+
* A scheduler or other engine-infrastructure failure rejects after the runner coherently
|
|
3781
|
+
* stops remaining work and attempts final persistence.
|
|
3379
3782
|
*/
|
|
3380
3783
|
export declare interface WorkflowResult {
|
|
3381
3784
|
readonly workflow: WorkflowInterface;
|
|
3382
3785
|
readonly status: WorkflowStatus;
|
|
3383
3786
|
readonly results: readonly TaskResult[];
|
|
3787
|
+
/** Whether the returned final state is stored; omitted when no store was supplied. */
|
|
3788
|
+
readonly durable?: boolean;
|
|
3789
|
+
/** The first required persistence failure; omitted when none occurred. */
|
|
3790
|
+
readonly fault?: WorkflowFault;
|
|
3384
3791
|
}
|
|
3385
3792
|
|
|
3386
3793
|
/**
|
|
@@ -3392,21 +3799,21 @@ export declare interface WorkflowResult {
|
|
|
3392
3799
|
* - **Composes, never re-implements.** Per-phase bounded concurrency is one
|
|
3393
3800
|
* {@link createRunner} per phase (the substrate {@link RunnerInterface} over the workers
|
|
3394
3801
|
* `Queue`); `bail` maps onto that Runner's fail-fast vs settle-all; the run-level abort /
|
|
3395
|
-
* timeout / budget / entity `signal` fold through
|
|
3396
|
-
* `AbortSignal.any` (exactly as the agent runtime folds its bounds);
|
|
3802
|
+
* timeout / budget / entity `signal` fold through the `@orkestrel/abort` signal contract,
|
|
3803
|
+
* {@link createTimeout}, and `AbortSignal.any` (exactly as the agent runtime folds its bounds);
|
|
3804
|
+
* pacing is the shipped
|
|
3397
3805
|
* {@link SchedulerInterface}. The runner writes ZERO concurrency / retry / abort logic of
|
|
3398
3806
|
* its own — it only sequences phases, dispatches a task's own handler, and drives the live
|
|
3399
|
-
* entity.
|
|
3400
|
-
*
|
|
3401
|
-
*
|
|
3807
|
+
* entity. The workflow layer owns per-task deadlines because timeout settlement must
|
|
3808
|
+
* update the live leaf under the phase's `bail` policy before the substrate unit settles.
|
|
3809
|
+
* - **Pure engine — no integration registry.** The runner carries no behavior or provider
|
|
3810
|
+
* registry: each live {@link TaskInterface} already
|
|
3402
3811
|
* resolved its own {@link import('./types.js').WorkflowFunction} into
|
|
3403
3812
|
* {@link import('./types.js').TaskInterface.handler} ONCE at construction (build, restore,
|
|
3404
3813
|
* or a live mint all resolve it identically, from {@link WorkflowOptions.functions}), so
|
|
3405
|
-
* dispatch is simply "invoke the task's own handler".
|
|
3406
|
-
*
|
|
3407
|
-
* {@link
|
|
3408
|
-
* {@link WorkflowOptions.functions} like any other behavior. This module never imports
|
|
3409
|
-
* any tool/agent package.
|
|
3814
|
+
* dispatch is simply "invoke the task's own handler". Provider, protocol, and tool
|
|
3815
|
+
* integrations remain application-owned {@link import('./types.js').WorkflowFunction}s
|
|
3816
|
+
* composed into {@link WorkflowOptions.functions}. This module imports none of them.
|
|
3410
3817
|
* - **Two `execute` forms, one engine.** `execute(definition, options)` BUILDS the live tree
|
|
3411
3818
|
* from a {@link WorkflowDefinition} (single source of truth for the `run` / `concurrency`
|
|
3412
3819
|
* metadata); `execute(workflow, options)` DRIVES a caller-owned, ALREADY-BUILT
|
|
@@ -3426,10 +3833,9 @@ export declare interface WorkflowResult {
|
|
|
3426
3833
|
* for `spawn` to accept (the runner already drained) is swept `skip`ped afterward so the
|
|
3427
3834
|
* phase always reaches a coherent terminal state.
|
|
3428
3835
|
* - **Dispatch by handler.** `#runTask` invokes the live task's own
|
|
3429
|
-
* {@link import('./types.js').TaskInterface.handler} directly
|
|
3430
|
-
*
|
|
3431
|
-
*
|
|
3432
|
-
* task's {@link import('./types.js').TaskControllerInterface} handle.
|
|
3836
|
+
* {@link import('./types.js').TaskInterface.handler} directly. An omitted `run` deliberately
|
|
3837
|
+
* auto-completes with JSON `null`; a present unresolved name is rejected by the synchronous
|
|
3838
|
+
* execution claim and never false-completes.
|
|
3433
3839
|
* - **`bail` → substrate.** Under `bail: true` (halt) a genuine task failure `fail`s the leaf
|
|
3434
3840
|
* THEN re-throws, so the substrate Runner fail-fasts — it aborts the in-flight siblings
|
|
3435
3841
|
* (their `controller.signal` fires; a mid-flight sibling `skip`s) and rejects the phase run;
|
|
@@ -3437,11 +3843,12 @@ export declare interface WorkflowResult {
|
|
|
3437
3843
|
* Under `bail: false` (graceful) a failure `fail`s the leaf and RESOLVES (never throws), so
|
|
3438
3844
|
* the Runner settles every unit (allSettled) and the run finishes (the workflow derives
|
|
3439
3845
|
* `completed`, the failure recorded in the result tree).
|
|
3440
|
-
* - **Pause / stop / destroy gates.**
|
|
3441
|
-
*
|
|
3442
|
-
*
|
|
3443
|
-
*
|
|
3444
|
-
*
|
|
3846
|
+
* - **Pause / stop / destroy gates.** Workflow, phase, and task gates are checked before
|
|
3847
|
+
* dispatch, and a running handler can checkpoint their folded state through
|
|
3848
|
+
* {@link import('./types.js').TaskControllerInterface.wait}. Because the substrate acquires
|
|
3849
|
+
* concurrency before this handler gate, a paused task occupies one phase slot until resume;
|
|
3850
|
+
* already-running siblings continue and its per-attempt timeout keeps counting. A GRACEFUL
|
|
3851
|
+
* `workflow.stop()` (no signal involved) is caught at
|
|
3445
3852
|
* those same gates: not-yet-started work is `skip`ped, in-flight work finishes naturally. A
|
|
3446
3853
|
* HARD `workflow.destroy()` aborts {@link WorkflowInterface.signal}, which `#fold` has folded
|
|
3447
3854
|
* into the run's composed signal — so it cancels the active phase Runner (and every
|
|
@@ -3458,8 +3865,8 @@ export declare interface WorkflowResult {
|
|
|
3458
3865
|
* {@link TaskController} signal `AbortSignal.any`-combines the substrate per-unit signal with
|
|
3459
3866
|
* `runSignal`, so a handler observes either cause directly.
|
|
3460
3867
|
* - **Re-entrant-safe.** No shared per-run mutable field: the active-Runner holder is LOCAL to
|
|
3461
|
-
* each `#execute`, so a nested `execute`
|
|
3462
|
-
*
|
|
3868
|
+
* each `#execute`, so a nested application-level `execute` cannot clobber the outer run's
|
|
3869
|
+
* state.
|
|
3463
3870
|
*/
|
|
3464
3871
|
export declare class WorkflowRunner implements WorkflowRunnerInterface {
|
|
3465
3872
|
#private;
|
|
@@ -3482,6 +3889,8 @@ export declare class WorkflowRunner implements WorkflowRunnerInterface {
|
|
|
3482
3889
|
* {@link WorkflowRunOptions} abort / timeout / budget fires every in-flight task's signal
|
|
3483
3890
|
* and `stop`s the run. `execute` resolves (never rejects) on a cancel — the partial outcome
|
|
3484
3891
|
* is read from the returned {@link WorkflowResult} (its `workflow` / `status` / `results`).
|
|
3892
|
+
* An unexpected scheduler or engine-infrastructure failure rejects after remaining work is
|
|
3893
|
+
* stopped, swept, and final persistence is attempted.
|
|
3485
3894
|
*
|
|
3486
3895
|
* @param definition - The {@link WorkflowDefinition} to build the live tree from and drive
|
|
3487
3896
|
* @param options - The construction options ({@link WorkflowOptions}: `on` / `bail` /
|
|
@@ -3501,10 +3910,11 @@ export declare class WorkflowRunner implements WorkflowRunnerInterface {
|
|
|
3501
3910
|
* @remarks
|
|
3502
3911
|
* `createWorkflow` mints the live tree, this overload drives it, and the caller controls
|
|
3503
3912
|
* the SAME entity mid-run via its own `pause` / `resume` / `add` / `stop` / `destroy`
|
|
3504
|
-
* (AGENTS §10). Requires `workflow.status === 'pending'
|
|
3505
|
-
*
|
|
3506
|
-
*
|
|
3507
|
-
*
|
|
3913
|
+
* (AGENTS §10). Requires `workflow.status === 'pending'`, `!workflow.destroyed`, and no
|
|
3914
|
+
* prior execution claim. A process-local object-identity claim shared by all runner instances
|
|
3915
|
+
* is acquired synchronously and never released, so a same-object second call throws a `TRANSITION`
|
|
3916
|
+
* {@link WorkflowError} before any asynchronous status change. Once accepted, observable
|
|
3917
|
+
* semantics are byte-identical to the `definition` form —
|
|
3508
3918
|
* except the phase loop RE-READS the live tree every iteration, so a caller's live `add`
|
|
3509
3919
|
* mid-run is picked up and actually dispatched. `options` carries only the per-run bounds
|
|
3510
3920
|
* (`signal` / `timeout` / `budget`) — the construction half of {@link WorkflowRunOptions}
|
|
@@ -3542,8 +3952,8 @@ export declare class WorkflowRunner implements WorkflowRunnerInterface {
|
|
|
3542
3952
|
* {@link WorkflowOptions.functions}) and each phase's `concurrency` (so there is no
|
|
3543
3953
|
* separately-supplied workflow to drift from the definition). The freshly-built live tree is
|
|
3544
3954
|
* returned in {@link WorkflowResult.workflow}. The runner carries NO registry of its own — it
|
|
3545
|
-
* simply invokes each task's OWN {@link TaskInterface.handler};
|
|
3546
|
-
*
|
|
3955
|
+
* simply invokes each task's OWN {@link TaskInterface.handler}; an omitted `run` is the only
|
|
3956
|
+
* auto-completing no-op. The runner DRIVES the live entity (`start` → `complete` / `fail`), never
|
|
3547
3957
|
* re-implementing status. The `bail` policy maps onto the substrate's fail-fast (`bail: true`
|
|
3548
3958
|
* — the first failure aborts in-flight siblings and skips the rest) vs settle-all (`bail:
|
|
3549
3959
|
* false` — failures are recorded and the run finishes). The {@link WorkflowOptions} half of
|
|
@@ -3581,9 +3991,9 @@ export declare interface WorkflowRunnerInterface {
|
|
|
3581
3991
|
* **Programmer-error exception (AGENTS §12).** A PATHOLOGICAL `definition` (e.g. a
|
|
3582
3992
|
* duplicate phase or task `id`) THROWS SYNCHRONOUSLY at construction — before any phase
|
|
3583
3993
|
* runs, and before the returned `Promise` is even created — rather than resolving a
|
|
3584
|
-
* failed/partial {@link WorkflowResult}.
|
|
3585
|
-
*
|
|
3586
|
-
* a
|
|
3994
|
+
* failed/partial {@link WorkflowResult}. Unexpected scheduler or engine-infrastructure
|
|
3995
|
+
* failures may reject asynchronously after remaining work is stopped, swept, and final
|
|
3996
|
+
* persistence is attempted. Neither case is a domain task outcome to disguise as a result.
|
|
3587
3997
|
*
|
|
3588
3998
|
* @param definition - The {@link WorkflowDefinition} to build the live tree from and drive
|
|
3589
3999
|
* @param options - The construction options ({@link WorkflowOptions}: `on` / `bail` /
|
|
@@ -3599,10 +4009,11 @@ export declare interface WorkflowRunnerInterface {
|
|
|
3599
4009
|
* The entity itself is now the single control surface (no separate run handle):
|
|
3600
4010
|
* `createWorkflow` mints the live tree, this overload drives it, and the caller
|
|
3601
4011
|
* controls the SAME entity mid-run via its own `pause` / `resume` / `add` / `stop` /
|
|
3602
|
-
* `destroy` (AGENTS §10). Requires `workflow.status === 'pending'
|
|
3603
|
-
* `!workflow.destroyed
|
|
3604
|
-
*
|
|
3605
|
-
*
|
|
4012
|
+
* `destroy` (AGENTS §10). Requires `workflow.status === 'pending'`,
|
|
4013
|
+
* `!workflow.destroyed`, and no prior execution claim. A process-local object-identity claim
|
|
4014
|
+
* shared by every runner instance is acquired synchronously and never released, so a same-object
|
|
4015
|
+
* call throws a `TRANSITION` {@link import('./errors.js').WorkflowError} even before an
|
|
4016
|
+
* asynchronous status change. Once accepted, phases run
|
|
3606
4017
|
* SEQUENTIALLY and, within each phase, tasks CONCURRENTLY — byte-identical observable
|
|
3607
4018
|
* semantics to the `definition`-form `execute` — except the phase loop RE-READS the
|
|
3608
4019
|
* live `workflow.phases` / each phase's live `tasks` every iteration (a cursor over
|
|
@@ -3619,12 +4030,10 @@ export declare interface WorkflowRunnerInterface {
|
|
|
3619
4030
|
* {@link import('./factories.js').restoreWorkflow} behaves according to whether a
|
|
3620
4031
|
* {@link WorkflowFunctions} registry was supplied at that build: WITH a registry,
|
|
3621
4032
|
* each task's `run` name is re-resolved against it, so a matched task carries a real
|
|
3622
|
-
* handler and this overload actually DISPATCHES it, resuming real work.
|
|
3623
|
-
*
|
|
3624
|
-
*
|
|
3625
|
-
*
|
|
3626
|
-
* not `pending`) is rejected outright by the `workflow.status === 'pending'` guard
|
|
3627
|
-
* above — only a wholly `pending` restored tree is drivable.
|
|
4033
|
+
* handler and this overload actually DISPATCHES it, resuming real work. Without a registry,
|
|
4034
|
+
* the persisted {@link TaskInterface.run} remains visible for inspection while `handler` is
|
|
4035
|
+
* `undefined`, and this overload rejects the tree before dispatch. A quiescent recovered tree may contain
|
|
4036
|
+
* terminal work plus pending work; a tree with any `running` leaf is not drivable.
|
|
3628
4037
|
*
|
|
3629
4038
|
* @param workflow - The live {@link WorkflowInterface} to drive (its own entity surface —
|
|
3630
4039
|
* `pause` / `resume` / `add` / `stop` / `destroy` — is the caller's control seam)
|
|
@@ -3642,9 +4051,7 @@ export declare interface WorkflowRunnerInterface {
|
|
|
3642
4051
|
* @remarks
|
|
3643
4052
|
* The runner is a PURE engine — it carries no `functions` / `tools` / `agents` registry
|
|
3644
4053
|
* (each live task already resolved its own handler at construction from
|
|
3645
|
-
* {@link WorkflowOptions.functions})
|
|
3646
|
-
* an OPT-IN concern of the `@orkestrel/tool` package's adapter factories, which a caller
|
|
3647
|
-
* composes into its OWN `functions` registry.
|
|
4054
|
+
* {@link WorkflowOptions.functions}).
|
|
3648
4055
|
* - `scheduler` — the {@link SchedulerInterface} that paces the tree (a cooperative
|
|
3649
4056
|
* `yield` between phases). Omitted ⇒ the shipped cross-environment default
|
|
3650
4057
|
* ({@link createScheduler}).
|
|
@@ -3679,23 +4086,19 @@ export declare interface WorkflowRunnerOptions {
|
|
|
3679
4086
|
* {@link TaskControllerInterface.signal} fires) and HALTS the run — the remaining tasks
|
|
3680
4087
|
* and phases are `skip`ped and the workflow settles `stopped`.
|
|
3681
4088
|
* - `signal` — an external cancellation (a caller `AbortController`).
|
|
3682
|
-
* - `timeout` — a whole-run deadline in milliseconds. A non-positive
|
|
3683
|
-
*
|
|
3684
|
-
* only when `timeout > 0`).
|
|
4089
|
+
* - `timeout` — a whole-run deadline in milliseconds. A non-positive, non-finite, or
|
|
4090
|
+
* over-`MAX_TIMER_MS` value means no deadline.
|
|
3685
4091
|
* - `budget` — a whole-run cost ceiling (a {@link BudgetInterface} over {@link TokenUsage}
|
|
3686
4092
|
* — its `signal` fires when a task-reported usage crosses `max`); the runner folds its
|
|
3687
4093
|
* `signal` and `start`s it. (A `max: 0` budget is exhausted from its first `start`, so it
|
|
3688
4094
|
* cancels the run at entry — a DIFFERENT primitive from the `timeout: 0` "no deadline" case.)
|
|
3689
4095
|
*
|
|
3690
|
-
* The engine itself carries NO nesting bookkeeping — the depth / cycle guard for a nested
|
|
3691
|
-
* `agent` → workflow-tool → workflow chain lives entirely in the OPT-IN adapter factories
|
|
3692
|
-
* shipped by `@orkestrel/tool`, closed over their own `depth` / `ancestry`, never threaded
|
|
3693
|
-
* through `execute`'s options.
|
|
3694
4096
|
*/
|
|
3695
4097
|
export declare type WorkflowRunOptions = WorkflowOptions & {
|
|
3696
4098
|
readonly signal?: AbortSignal;
|
|
3697
4099
|
readonly timeout?: number;
|
|
3698
4100
|
readonly budget?: BudgetInterface<TokenUsage>;
|
|
4101
|
+
readonly store?: WorkflowStoreInterface;
|
|
3699
4102
|
};
|
|
3700
4103
|
|
|
3701
4104
|
/**
|
|
@@ -3738,17 +4141,18 @@ export declare const workflowShape: ObjectShape<{
|
|
|
3738
4141
|
* it is self-contained, it carries the policy it ran under: `bail` (AGENTS §4.4) is the
|
|
3739
4142
|
* failure policy, so {@link import('./factories.js').restoreWorkflow} re-derives status
|
|
3740
4143
|
* IDENTICALLY without a silent default. `status` is the EFFECTIVE status (override-or-derived)
|
|
3741
|
-
* at snapshot time; `override` is the forced status of a whole-workflow `skip` / `stop
|
|
3742
|
-
*
|
|
3743
|
-
*
|
|
3744
|
-
*
|
|
4144
|
+
* at snapshot time; `override` is the forced status of a whole-workflow `skip` / `stop` or
|
|
4145
|
+
* vacuous `completed`. The completed override is valid only for an otherwise-derived pending
|
|
4146
|
+
* tree containing no tasks. An override is PRESENT only when one is in force (so a restore
|
|
4147
|
+
* reinstates it DIRECTLY rather than guessing from a status divergence). `phases` are the
|
|
4148
|
+
* workflow's {@link PhaseSnapshot}s in order; `created` / `updated` are ms since epoch.
|
|
3745
4149
|
*/
|
|
3746
4150
|
export declare interface WorkflowSnapshot {
|
|
3747
4151
|
readonly id: string;
|
|
3748
4152
|
readonly name: string;
|
|
3749
4153
|
readonly description?: string;
|
|
3750
4154
|
readonly status: WorkflowStatus;
|
|
3751
|
-
/**
|
|
4155
|
+
/** Whole-workflow `skip` / `stop` or valid task-free vacuous `completed`; omitted when derived. */
|
|
3752
4156
|
readonly override?: WorkflowStatus;
|
|
3753
4157
|
/** The failure policy the workflow ran under (AGENTS §4.4) — persisted so a restore re-derives identically. */
|
|
3754
4158
|
readonly bail: boolean;
|
|
@@ -3757,6 +4161,9 @@ export declare interface WorkflowSnapshot {
|
|
|
3757
4161
|
readonly updated: number;
|
|
3758
4162
|
}
|
|
3759
4163
|
|
|
4164
|
+
/** Locate the nearest identifiable node for an inconsistent owned snapshot. */
|
|
4165
|
+
export declare function workflowSnapshotContext(value: unknown): Readonly<Record<string, unknown>> | undefined;
|
|
4166
|
+
|
|
3760
4167
|
/**
|
|
3761
4168
|
* One row of the table a {@link import('./stores/DatabaseWorkflowStore.js').DatabaseWorkflowStore}
|
|
3762
4169
|
* persists — a workflow `id` plus its {@link WorkflowSnapshot} held as ONE OPAQUE JSON column.
|
|
@@ -3792,8 +4199,8 @@ export declare type WorkflowStatus = LifecycleStatus;
|
|
|
3792
4199
|
/**
|
|
3793
4200
|
* The durable persistence seam for a {@link WorkflowSnapshot} — three async primitives
|
|
3794
4201
|
* (`get` / `set` / `delete`) keyed by a workflow id, the snapshot analogue of
|
|
3795
|
-
* the server package's `SessionStoreInterface` (and the
|
|
3796
|
-
*
|
|
4202
|
+
* the server package's `SessionStoreInterface` (and the `@orkestrel/queue`
|
|
4203
|
+
* `QueueStoreInterface` driver-swap pattern).
|
|
3797
4204
|
*
|
|
3798
4205
|
* @remarks
|
|
3799
4206
|
* The store persists the W-a {@link WorkflowSnapshot} — the COMPLETE, self-contained,
|
|
@@ -3806,7 +4213,7 @@ export declare type WorkflowStatus = LifecycleStatus;
|
|
|
3806
4213
|
*
|
|
3807
4214
|
* Every primitive is async (a `Promise`), so a durable backend (a database round-trip) fits the
|
|
3808
4215
|
* same shape as the memory one. The snapshot carries its OWN id, so `set` takes no separate id
|
|
3809
|
-
* param (mirroring
|
|
4216
|
+
* param (mirroring `QueueStoreInterface.save` from `@orkestrel/queue` / the server package's
|
|
3810
4217
|
* `SessionStoreInterface.set`, which key off the value's own
|
|
3811
4218
|
* `id`). UNLIKE a session store there is NO idle-TTL / eviction — a persisted workflow run-state
|
|
3812
4219
|
* lives until an explicit `delete`, never silently expiring (it is durable orchestration state,
|
|
@@ -3816,6 +4223,8 @@ export declare type WorkflowStatus = LifecycleStatus;
|
|
|
3816
4223
|
export declare interface WorkflowStoreInterface {
|
|
3817
4224
|
/**
|
|
3818
4225
|
* Resolve the persisted snapshot for `id`, or `undefined` if none is stored.
|
|
4226
|
+
* A present payload whose own `id` differs from the requested storage key is corrupt and
|
|
4227
|
+
* rejects with a normalized `RESTORE` error carrying both ids.
|
|
3819
4228
|
*
|
|
3820
4229
|
* @param id - The workflow id to resolve (a {@link WorkflowSnapshot.id})
|
|
3821
4230
|
* @returns The persisted snapshot, or `undefined` if absent
|
|
@@ -3823,7 +4232,7 @@ export declare interface WorkflowStoreInterface {
|
|
|
3823
4232
|
get(id: string): Promise<WorkflowSnapshot | undefined>;
|
|
3824
4233
|
/**
|
|
3825
4234
|
* Insert or replace a snapshot under its own `snapshot.id` (no separate id param —
|
|
3826
|
-
* mirroring
|
|
4235
|
+
* mirroring `QueueStoreInterface.save` from `@orkestrel/queue`).
|
|
3827
4236
|
*
|
|
3828
4237
|
* @param snapshot - The snapshot to store (keyed by its `id`)
|
|
3829
4238
|
*/
|