@gobing-ai/ts-dual-workflow-engine 0.3.1 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/README.md +506 -5
  2. package/dist/config.d.ts +1 -0
  3. package/dist/config.d.ts.map +1 -1
  4. package/dist/config.js +7 -11
  5. package/dist/events.d.ts +49 -0
  6. package/dist/events.d.ts.map +1 -0
  7. package/dist/events.js +0 -0
  8. package/dist/extensions.d.ts +60 -0
  9. package/dist/extensions.d.ts.map +1 -0
  10. package/dist/extensions.js +85 -0
  11. package/dist/index.d.ts +5 -2
  12. package/dist/index.d.ts.map +1 -1
  13. package/dist/index.js +3 -1
  14. package/dist/run-lifecycle.d.ts +58 -0
  15. package/dist/run-lifecycle.d.ts.map +1 -0
  16. package/dist/run-lifecycle.js +149 -0
  17. package/dist/schema-sql.d.ts +1 -0
  18. package/dist/schema-sql.d.ts.map +1 -1
  19. package/dist/schema-sql.js +1 -0
  20. package/dist/schema.d.ts +44 -0
  21. package/dist/schema.d.ts.map +1 -1
  22. package/dist/schema.js +3 -0
  23. package/dist/state-machine.d.ts +7 -2
  24. package/dist/state-machine.d.ts.map +1 -1
  25. package/dist/state-machine.js +63 -72
  26. package/dist/transition-flow.d.ts +1 -2
  27. package/dist/transition-flow.d.ts.map +1 -1
  28. package/dist/transition-flow.js +35 -61
  29. package/dist/types.d.ts +14 -0
  30. package/dist/types.d.ts.map +1 -1
  31. package/dist/variables.d.ts +6 -1
  32. package/dist/variables.d.ts.map +1 -1
  33. package/dist/variables.js +7 -0
  34. package/package.json +4 -4
  35. package/src/config.ts +8 -11
  36. package/src/events.ts +19 -0
  37. package/src/extensions.ts +163 -0
  38. package/src/index.ts +24 -1
  39. package/src/run-lifecycle.ts +211 -0
  40. package/src/schema-sql.ts +1 -0
  41. package/src/schema.ts +3 -0
  42. package/src/state-machine.ts +78 -128
  43. package/src/transition-flow.ts +47 -105
  44. package/src/types.ts +16 -0
  45. package/src/variables.ts +13 -1
@@ -0,0 +1,60 @@
1
+ import type { Logger } from '@gobing-ai/ts-infra';
2
+ import type { WorkflowEngineHost } from './host';
3
+ /** Minimal warning sink accepted for non-fatal extension diagnostics; a full {@link Logger} satisfies it. */
4
+ export type WorkflowExtensionLogger = Pick<Logger, 'warn'>;
5
+ /**
6
+ * Capability kinds a workflow extension module can contribute.
7
+ *
8
+ * Only `actions` and `guards` are supported as extension surfaces. Driver,
9
+ * loader, validator, and formatter registries are explicitly deferred per
10
+ * ADR-010 and are not extension-loadable.
11
+ */
12
+ export type WorkflowExtensionKind = 'actions' | 'guards';
13
+ /**
14
+ * A single workflow extension module reference.
15
+ *
16
+ * The caller provides a pre-resolved absolute path; the loader adapts it to the
17
+ * shared `ExtensionRef` format before delegating to the generic core so the
18
+ * trust guard always governs the module that gets imported.
19
+ */
20
+ export interface WorkflowExtensionRef {
21
+ /** Target capability registry. */
22
+ readonly kind: WorkflowExtensionKind;
23
+ /** Absolute path to the module to import. */
24
+ readonly absPath: string;
25
+ /** Name of the config declaring this extension (for diagnostics). */
26
+ readonly sourceName: string;
27
+ }
28
+ /** Options controlling workflow extension loading. */
29
+ export interface LoadWorkflowExtensionsOptions {
30
+ /**
31
+ * Whether to actually import extension modules. Defaults to `false`:
32
+ * loading arbitrary code is a trust decision the caller must make
33
+ * explicitly. When refs exist and this is not `true`, loading throws
34
+ * **before any import**.
35
+ */
36
+ readonly allowExtensions?: boolean;
37
+ /** Optional sink for non-fatal warnings (e.g. built-in overrides). */
38
+ readonly logger?: WorkflowExtensionLogger;
39
+ /**
40
+ * Required module loader seam for tests or embedders with custom import
41
+ * policy. The shared core has no ambient code-loading capability of its
42
+ * own; the embedder supplies the import policy.
43
+ */
44
+ readonly moduleLoader: (absPath: string) => Promise<Record<string, unknown>>;
45
+ }
46
+ /**
47
+ * Import each extension module behind an explicit trust gate and register
48
+ * its actions and/or guards on the workflow host.
49
+ *
50
+ * Delegates generic loading (gate, path guard, module import, export
51
+ * validation) to the shared ``loadExtensionModules`` from ts-runtime/plugin,
52
+ * then routes each capability to ``host.registerAction`` or
53
+ * ``host.registerGuard`` based on ``ref.kind``.
54
+ *
55
+ * @throws When extensions are present but ``allowExtensions`` is not ``true``,
56
+ * when a module lacks a valid export shape, or when the module's export
57
+ * does not contain entries matching ``ref.kind``.
58
+ */
59
+ export declare function loadWorkflowExtensionsIntoHost(host: WorkflowEngineHost, refs: readonly WorkflowExtensionRef[], options: LoadWorkflowExtensionsOptions): Promise<void>;
60
+ //# sourceMappingURL=extensions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extensions.d.ts","sourceRoot":"","sources":["../src/extensions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAKlD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,QAAQ,CAAC;AAGjD,6GAA6G;AAC7G,MAAM,MAAM,uBAAuB,GAAG,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAE3D;;;;;;GAMG;AACH,MAAM,MAAM,qBAAqB,GAAG,SAAS,GAAG,QAAQ,CAAC;AAEzD;;;;;;GAMG;AACH,MAAM,WAAW,oBAAoB;IACjC,kCAAkC;IAClC,QAAQ,CAAC,IAAI,EAAE,qBAAqB,CAAC;IACrC,6CAA6C;IAC7C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,qEAAqE;IACrE,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC/B;AAED,sDAAsD;AACtD,MAAM,WAAW,6BAA6B;IAC1C;;;;;OAKG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,CAAC;IACnC,sEAAsE;IACtE,QAAQ,CAAC,MAAM,CAAC,EAAE,uBAAuB,CAAC;IAC1C;;;;OAIG;IACH,QAAQ,CAAC,YAAY,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CAChF;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,8BAA8B,CAChD,IAAI,EAAE,kBAAkB,EACxB,IAAI,EAAE,SAAS,oBAAoB,EAAE,EACrC,OAAO,EAAE,6BAA6B,GACvC,OAAO,CAAC,IAAI,CAAC,CAqCf"}
@@ -0,0 +1,85 @@
1
+ import { basenamePath, dirnamePath, SEP } from '@gobing-ai/ts-runtime';
2
+ import { loadExtensionModules } from '@gobing-ai/ts-runtime/plugin';
3
+ import { WorkflowValidationError } from './errors.js';
4
+ /**
5
+ * Import each extension module behind an explicit trust gate and register
6
+ * its actions and/or guards on the workflow host.
7
+ *
8
+ * Delegates generic loading (gate, path guard, module import, export
9
+ * validation) to the shared ``loadExtensionModules`` from ts-runtime/plugin,
10
+ * then routes each capability to ``host.registerAction`` or
11
+ * ``host.registerGuard`` based on ``ref.kind``.
12
+ *
13
+ * @throws When extensions are present but ``allowExtensions`` is not ``true``,
14
+ * when a module lacks a valid export shape, or when the module's export
15
+ * does not contain entries matching ``ref.kind``.
16
+ */
17
+ export async function loadWorkflowExtensionsIntoHost(host, refs, options) {
18
+ if (refs.length === 0)
19
+ return;
20
+ // Enforce relative-path guard before adapting to the shared format.
21
+ // The shared loader's assertRelativeExtensionPath applies to the derived
22
+ // (basename) path, which is always clean — this pre-check catches `..`
23
+ // traversal in the caller-supplied absPath before basename strips it (R6).
24
+ for (const ref of refs) {
25
+ const segments = ref.absPath.split(SEP);
26
+ if (segments.includes('..')) {
27
+ throw new Error(`extension path "${ref.absPath}" declared by "${ref.sourceName}" must not contain ".." traversal`);
28
+ }
29
+ }
30
+ // Adapt WorkflowExtensionRef → shared ExtensionRef so the generic loader
31
+ // governs every import. The shared loader resolves (baseDir, path) ->
32
+ // absPath internally; we supply dirname/basename so the resolved path
33
+ // reconstructs the caller's original absPath. assertRelativeExtensionPath
34
+ // is satisfied because basenamePath() is always a simple filename.
35
+ const sharedRefs = refs.map((ref) => ({
36
+ kind: ref.kind,
37
+ path: `./${basenamePath(ref.absPath)}`,
38
+ baseDir: dirnamePath(ref.absPath),
39
+ sourceName: ref.sourceName,
40
+ }));
41
+ const sharedOptions = {
42
+ allowExtensions: options.allowExtensions,
43
+ logger: options.logger,
44
+ moduleLoader: options.moduleLoader,
45
+ };
46
+ await loadExtensionModules(sharedRefs, sharedOptions, async (sharedRef, extension) => {
47
+ await registerExtensionOnHost(host, sharedRef, extension, options.logger);
48
+ });
49
+ }
50
+ /**
51
+ * Route extension-exported capabilities to the correct host registry.
52
+ *
53
+ * Validates that the module export contains entries matching `ref.kind`
54
+ * (wrong-kind-for-ref throws ``WorkflowValidationError``), registers each
55
+ * with origin ``'extension'``, and warns on built-in overrides.
56
+ */
57
+ async function registerExtensionOnHost(host, ref, extension, logger) {
58
+ const name = extension.name;
59
+ if (ref.kind === 'actions') {
60
+ const actions = extension.actions;
61
+ if (!Array.isArray(actions)) {
62
+ throw new WorkflowValidationError(`"${ref.sourceName}" extension "${name}" is referenced as kind "actions" but does not export an actions[] array`);
63
+ }
64
+ for (const action of actions) {
65
+ warnIfOverride(host, action.kind, 'action', ref.sourceName, logger);
66
+ host.registerAction(action, 'extension');
67
+ }
68
+ }
69
+ else {
70
+ const guards = extension.guards;
71
+ if (!Array.isArray(guards)) {
72
+ throw new WorkflowValidationError(`"${ref.sourceName}" extension "${name}" is referenced as kind "guards" but does not export a guards[] array`);
73
+ }
74
+ for (const guard of guards) {
75
+ warnIfOverride(host, guard.kind, 'guard', ref.sourceName, logger);
76
+ host.registerGuard(guard, 'extension');
77
+ }
78
+ }
79
+ }
80
+ function warnIfOverride(host, kind, capabilityType, sourceName, logger) {
81
+ const origin = capabilityType === 'action' ? host.actionOrigin(kind) : host.guardOrigin(kind);
82
+ if (logger && origin === 'builtin') {
83
+ logger.warn(`"${sourceName}" extension overrides built-in ${capabilityType} "${kind}"`);
84
+ }
85
+ }
package/dist/index.d.ts CHANGED
@@ -1,12 +1,15 @@
1
1
  export { loadWorkflowDef, loadWorkflowDefFromText, validateWorkflowDef } from './config';
2
2
  export { FSMError, RunCollisionError, WorkflowValidationError } from './errors';
3
+ export type { WorkflowEngineEvents } from './events';
4
+ export { type LoadWorkflowExtensionsOptions, loadWorkflowExtensionsIntoHost, type WorkflowExtensionKind, type WorkflowExtensionLogger, type WorkflowExtensionRef, } from './extensions';
3
5
  export { createDefaultWorkflowEngineHost, NoteActionRunner, ShellActionRunner, WorkflowEngineHost, } from './host';
4
6
  export { applyWorkflowEngineSchema, DbWorkflowPersistenceAdapter, MemoryWorkflowPersistenceAdapter, } from './persistence';
7
+ export { allowedEnv, RUNTIME_BUILTIN_KEYS, RunLifecycle, type RunLifecycleDeps, runtimeBuiltins, type WorkflowMode, } from './run-lifecycle';
5
8
  export { ActionDefSchema, GuardDefSchema, StateMachineWorkflowDefSchema, TransitionFlowWorkflowDefSchema, WorkflowDefSchema, } from './schema';
6
9
  export { WORKFLOW_ENGINE_SCHEMA_SQL } from './schema-sql';
7
10
  export { WorkflowService } from './service';
8
11
  export { StateMachineDriver, type StateMachineDriverOptions } from './state-machine';
9
12
  export { TransitionFlowDriver, type TransitionFlowDriverOptions } from './transition-flow';
10
- export type { ActionDef, ActionResult, ActionRunContext, ActionRunner, Env, FlowEdgeDef, FlowNodeDef, GuardContext, GuardDef, GuardRunner, StateDef, StateMachineWorkflowDef, TransitionDef, TransitionFlowWorkflowDef, Vars, WorkflowDef, WorkflowPersistenceAdapter, WorkflowRunOptions, WorkflowRunRecord, WorkflowRunResult, WorkflowStatus, } from './types';
11
- export { mergeVars, resolveTemplateString, resolveTemplates, type VariableContext } from './variables';
13
+ export type { ActionDef, ActionResult, ActionRunContext, ActionRunner, Env, FlowEdgeDef, FlowNodeDef, GuardContext, GuardDef, GuardRunner, OnErrorPolicy, StateDef, StateMachineWorkflowDef, TransitionDef, TransitionFlowWorkflowDef, Vars, WorkflowDef, WorkflowPersistenceAdapter, WorkflowRunOptions, WorkflowRunRecord, WorkflowRunResult, WorkflowStatus, } from './types';
14
+ export { mergeVars, resolveOnErrorPolicy, resolveTemplateString, resolveTemplates, type VariableContext, } from './variables';
12
15
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,uBAAuB,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AACzF,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,MAAM,UAAU,CAAC;AAChF,OAAO,EACH,+BAA+B,EAC/B,gBAAgB,EAChB,iBAAiB,EACjB,kBAAkB,GACrB,MAAM,QAAQ,CAAC;AAChB,OAAO,EACH,yBAAyB,EACzB,4BAA4B,EAC5B,gCAAgC,GACnC,MAAM,eAAe,CAAC;AACvB,OAAO,EACH,eAAe,EACf,cAAc,EACd,6BAA6B,EAC7B,+BAA+B,EAC/B,iBAAiB,GACpB,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,EAAE,kBAAkB,EAAE,KAAK,yBAAyB,EAAE,MAAM,iBAAiB,CAAC;AACrF,OAAO,EAAE,oBAAoB,EAAE,KAAK,2BAA2B,EAAE,MAAM,mBAAmB,CAAC;AAC3F,YAAY,EACR,SAAS,EACT,YAAY,EACZ,gBAAgB,EAChB,YAAY,EACZ,GAAG,EACH,WAAW,EACX,WAAW,EACX,YAAY,EACZ,QAAQ,EACR,WAAW,EACX,QAAQ,EACR,uBAAuB,EACvB,aAAa,EACb,yBAAyB,EACzB,IAAI,EACJ,WAAW,EACX,0BAA0B,EAC1B,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EACjB,cAAc,GACjB,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,SAAS,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,uBAAuB,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AACzF,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,MAAM,UAAU,CAAC;AAChF,YAAY,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AACrD,OAAO,EACH,KAAK,6BAA6B,EAClC,8BAA8B,EAC9B,KAAK,qBAAqB,EAC1B,KAAK,uBAAuB,EAC5B,KAAK,oBAAoB,GAC5B,MAAM,cAAc,CAAC;AACtB,OAAO,EACH,+BAA+B,EAC/B,gBAAgB,EAChB,iBAAiB,EACjB,kBAAkB,GACrB,MAAM,QAAQ,CAAC;AAChB,OAAO,EACH,yBAAyB,EACzB,4BAA4B,EAC5B,gCAAgC,GACnC,MAAM,eAAe,CAAC;AACvB,OAAO,EACH,UAAU,EACV,oBAAoB,EACpB,YAAY,EACZ,KAAK,gBAAgB,EACrB,eAAe,EACf,KAAK,YAAY,GACpB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACH,eAAe,EACf,cAAc,EACd,6BAA6B,EAC7B,+BAA+B,EAC/B,iBAAiB,GACpB,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,EAAE,kBAAkB,EAAE,KAAK,yBAAyB,EAAE,MAAM,iBAAiB,CAAC;AACrF,OAAO,EAAE,oBAAoB,EAAE,KAAK,2BAA2B,EAAE,MAAM,mBAAmB,CAAC;AAC3F,YAAY,EACR,SAAS,EACT,YAAY,EACZ,gBAAgB,EAChB,YAAY,EACZ,GAAG,EACH,WAAW,EACX,WAAW,EACX,YAAY,EACZ,QAAQ,EACR,WAAW,EACX,aAAa,EACb,QAAQ,EACR,uBAAuB,EACvB,aAAa,EACb,yBAAyB,EACzB,IAAI,EACJ,WAAW,EACX,0BAA0B,EAC1B,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EACjB,cAAc,GACjB,MAAM,SAAS,CAAC;AACjB,OAAO,EACH,SAAS,EACT,oBAAoB,EACpB,qBAAqB,EACrB,gBAAgB,EAChB,KAAK,eAAe,GACvB,MAAM,aAAa,CAAC"}
package/dist/index.js CHANGED
@@ -1,10 +1,12 @@
1
1
  export { loadWorkflowDef, loadWorkflowDefFromText, validateWorkflowDef } from './config.js';
2
2
  export { FSMError, RunCollisionError, WorkflowValidationError } from './errors.js';
3
+ export { loadWorkflowExtensionsIntoHost, } from './extensions.js';
3
4
  export { createDefaultWorkflowEngineHost, NoteActionRunner, ShellActionRunner, WorkflowEngineHost, } from './host.js';
4
5
  export { applyWorkflowEngineSchema, DbWorkflowPersistenceAdapter, MemoryWorkflowPersistenceAdapter, } from './persistence.js';
6
+ export { allowedEnv, RUNTIME_BUILTIN_KEYS, RunLifecycle, runtimeBuiltins, } from './run-lifecycle.js';
5
7
  export { ActionDefSchema, GuardDefSchema, StateMachineWorkflowDefSchema, TransitionFlowWorkflowDefSchema, WorkflowDefSchema, } from './schema.js';
6
8
  export { WORKFLOW_ENGINE_SCHEMA_SQL } from './schema-sql.js';
7
9
  export { WorkflowService } from './service.js';
8
10
  export { StateMachineDriver } from './state-machine.js';
9
11
  export { TransitionFlowDriver } from './transition-flow.js';
10
- export { mergeVars, resolveTemplateString, resolveTemplates } from './variables.js';
12
+ export { mergeVars, resolveOnErrorPolicy, resolveTemplateString, resolveTemplates, } from './variables.js';
@@ -0,0 +1,58 @@
1
+ import { type EventBus, type Logger } from '@gobing-ai/ts-infra';
2
+ import type { WorkflowEngineEvents } from './events';
3
+ import type { WorkflowPersistenceAdapter, WorkflowRunOptions, WorkflowRunResult } from './types';
4
+ /** Workflow dialect carried on every run, span, and persisted record. */
5
+ export type WorkflowMode = WorkflowRunResult['mode'];
6
+ /** Keys of the runtime builtin namespace, single-sourced for resolver + validator. */
7
+ export declare const RUNTIME_BUILTIN_KEYS: readonly ["workflow", "runId", "task", "state", "node", "iteration", "run", "runtime"];
8
+ /** Built-in bare template values available to action options (state-machine + transition-flow). */
9
+ export declare function runtimeBuiltins(workflowName: string, stateOrNodeId: string, runId: string, transitionsTaken: number, mode: WorkflowMode): Record<(typeof RUNTIME_BUILTIN_KEYS)[number], string | number>;
10
+ /** Project the env allowlist over a source map, dropping unset names. */
11
+ export declare function allowedEnv(names: readonly string[], source?: Record<string, string | undefined>): Record<string, string>;
12
+ /** Dependencies a driver hands to {@link RunLifecycle}. */
13
+ export interface RunLifecycleDeps {
14
+ readonly persistence: WorkflowPersistenceAdapter;
15
+ /** Observability sink; defaults to the shared `workflow` category logger. */
16
+ readonly logger?: Logger;
17
+ /** Optional event bus for structured in-process run observability. */
18
+ readonly events?: EventBus<WorkflowEngineEvents>;
19
+ }
20
+ /**
21
+ * Owns the run-level bookkeeping shared by both drivers: run identity, the
22
+ * create→phase→finalize persistence sequence, and observability (one OTel span
23
+ * per run plus structured log lines). The two driver control loops stay
24
+ * dialect-specific (ADR-006 §7) and call into this for every persistence touch.
25
+ */
26
+ export declare class RunLifecycle {
27
+ private readonly workflowName;
28
+ private readonly mode;
29
+ readonly runId: string;
30
+ private readonly persistence;
31
+ private readonly events;
32
+ private readonly logger;
33
+ private readonly startedAt;
34
+ private constructor();
35
+ /**
36
+ * Create the run record and execute `loop` inside the run's OTel span. The
37
+ * driver's control loop is the body; it receives this lifecycle to drive
38
+ * per-step persistence and terminal results.
39
+ */
40
+ static run(workflowName: string, mode: WorkflowMode, deps: RunLifecycleDeps, options: WorkflowRunOptions, loop: (lifecycle: RunLifecycle) => Promise<WorkflowRunResult>): Promise<WorkflowRunResult>;
41
+ /** Persist the current state/node snapshot and mark its phase running. */
42
+ enter(stateOrNodeId: string, transitionsTaken: number): Promise<void>;
43
+ /** Persist a transition and emit its observability event. */
44
+ recordTransition(from: string, to: string, trigger: string | null): Promise<void>;
45
+ /** Finalize the run as succeeded and return its result. */
46
+ done(finalState: string, transitionsTaken: number): Promise<WorkflowRunResult>;
47
+ /** Finalize the run as failed and return its result. */
48
+ fail(finalState: string, transitionsTaken: number, reason?: string): Promise<WorkflowRunResult>;
49
+ /** Emit action-level observability before a host action is invoked. */
50
+ actionStart(stateOrNodeId: string, kind: string): void;
51
+ /** Emit action-level observability after a host action settles. */
52
+ actionDone(stateOrNodeId: string, kind: string, durationMs: number, ok: boolean): void;
53
+ /** Log and trace a non-fatal action failure for the 'continue' error policy (ADR-013 observability seam). */
54
+ warnActionFailed(stateOrNodeId: string, transitionsTaken: number, error?: string): void;
55
+ private result;
56
+ private runRecord;
57
+ }
58
+ //# sourceMappingURL=run-lifecycle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-lifecycle.d.ts","sourceRoot":"","sources":["../src/run-lifecycle.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,149 @@
1
+ import { addSpanEvent, getLogger, traceAsync } from '@gobing-ai/ts-infra';
2
+ import { getProcessEnv } from '@gobing-ai/ts-runtime';
3
+ /** Keys of the runtime builtin namespace, single-sourced for resolver + validator. */
4
+ export const RUNTIME_BUILTIN_KEYS = [
5
+ 'workflow',
6
+ 'runId',
7
+ 'task',
8
+ 'state',
9
+ 'node',
10
+ 'iteration',
11
+ 'run',
12
+ 'runtime',
13
+ ];
14
+ /** Built-in bare template values available to action options (state-machine + transition-flow). */
15
+ export function runtimeBuiltins(workflowName, stateOrNodeId, runId, transitionsTaken, mode) {
16
+ return {
17
+ workflow: workflowName,
18
+ runId,
19
+ task: workflowName,
20
+ state: stateOrNodeId,
21
+ node: stateOrNodeId,
22
+ iteration: transitionsTaken,
23
+ run: runId,
24
+ runtime: mode,
25
+ };
26
+ }
27
+ /** Project the env allowlist over a source map, dropping unset names. */
28
+ export function allowedEnv(names, source = getProcessEnv()) {
29
+ return Object.fromEntries(names.flatMap((name) => (source[name] === undefined ? [] : [[name, source[name]]])));
30
+ }
31
+ /**
32
+ * Owns the run-level bookkeeping shared by both drivers: run identity, the
33
+ * create→phase→finalize persistence sequence, and observability (one OTel span
34
+ * per run plus structured log lines). The two driver control loops stay
35
+ * dialect-specific (ADR-006 §7) and call into this for every persistence touch.
36
+ */
37
+ export class RunLifecycle {
38
+ workflowName;
39
+ mode;
40
+ runId;
41
+ persistence;
42
+ events;
43
+ logger;
44
+ startedAt;
45
+ constructor(runId, workflowName, mode, deps) {
46
+ this.workflowName = workflowName;
47
+ this.mode = mode;
48
+ this.runId = runId;
49
+ this.persistence = deps.persistence;
50
+ this.events = deps.events;
51
+ this.startedAt = new Date().toISOString();
52
+ this.logger = (deps.logger ?? getLogger('workflow')).child({ runId, workflow: workflowName, mode });
53
+ }
54
+ /**
55
+ * Create the run record and execute `loop` inside the run's OTel span. The
56
+ * driver's control loop is the body; it receives this lifecycle to drive
57
+ * per-step persistence and terminal results.
58
+ */
59
+ static async run(workflowName, mode, deps, options, loop) {
60
+ const runId = options.runId ?? crypto.randomUUID();
61
+ const lifecycle = new RunLifecycle(runId, workflowName, mode, deps);
62
+ return await traceAsync('workflow.run', async () => {
63
+ await lifecycle.persistence.createRun(lifecycle.runRecord(options.metadata));
64
+ lifecycle.logger.info('workflow run started');
65
+ addSpanEvent('workflow.run.started', { workflowName, mode, runId });
66
+ void lifecycle.events?.emit('workflow.run.started', { workflowName, mode, runId });
67
+ return await loop(lifecycle);
68
+ }, { attributes: { 'workflow.name': workflowName, 'workflow.mode': mode, 'workflow.run_id': runId } });
69
+ }
70
+ /** Persist the current state/node snapshot and mark its phase running. */
71
+ async enter(stateOrNodeId, transitionsTaken) {
72
+ await this.persistence.saveWorkflowState(this.runId, stateOrNodeId, { transitionsTaken });
73
+ await this.persistence.savePhase(this.runId, stateOrNodeId, 'running');
74
+ addSpanEvent('workflow.node.enter', { node: stateOrNodeId, transitionsTaken });
75
+ void this.events?.emit('workflow.node.enter', { node: stateOrNodeId, transitionsTaken });
76
+ this.logger.debug('entered', { node: stateOrNodeId, transitionsTaken });
77
+ }
78
+ /** Persist a transition and emit its observability event. */
79
+ async recordTransition(from, to, trigger) {
80
+ await this.persistence.saveTransition(this.runId, from, to, trigger);
81
+ addSpanEvent('workflow.node.transition', { from, to, ...(trigger === null ? {} : { trigger }) });
82
+ void this.events?.emit('workflow.node.transition', { from, to, trigger });
83
+ this.logger.debug('transition', { from, to, trigger });
84
+ }
85
+ /** Finalize the run as succeeded and return its result. */
86
+ async done(finalState, transitionsTaken) {
87
+ await this.persistence.savePhase(this.runId, finalState, 'done');
88
+ await this.persistence.finalizeRun(this.runId, 'done', new Date().toISOString());
89
+ this.logger.info('workflow run done', { finalState, transitionsTaken });
90
+ addSpanEvent('workflow.run.done', { finalState, transitionsTaken });
91
+ void this.events?.emit('workflow.run.done', { finalState, transitionsTaken });
92
+ return this.result('done', finalState, transitionsTaken);
93
+ }
94
+ /** Finalize the run as failed and return its result. */
95
+ async fail(finalState, transitionsTaken, reason = 'failed') {
96
+ await this.persistence.savePhase(this.runId, finalState, 'failed');
97
+ await this.persistence.finalizeRun(this.runId, 'failed', new Date().toISOString());
98
+ addSpanEvent('workflow.run.failed', { finalState, reason });
99
+ void this.events?.emit('workflow.run.failed', { finalState, reason });
100
+ this.logger.warn('workflow run failed', { finalState, transitionsTaken, reason });
101
+ return this.result('failed', finalState, transitionsTaken, reason);
102
+ }
103
+ /** Emit action-level observability before a host action is invoked. */
104
+ actionStart(stateOrNodeId, kind) {
105
+ addSpanEvent('workflow.action.start', { node: stateOrNodeId, kind });
106
+ void this.events?.emit('workflow.action.start', { node: stateOrNodeId, kind });
107
+ }
108
+ /** Emit action-level observability after a host action settles. */
109
+ actionDone(stateOrNodeId, kind, durationMs, ok) {
110
+ addSpanEvent('workflow.action.done', { node: stateOrNodeId, kind, durationMs, ok });
111
+ void this.events?.emit('workflow.action.done', { node: stateOrNodeId, kind, durationMs, ok });
112
+ }
113
+ /** Log and trace a non-fatal action failure for the 'continue' error policy (ADR-013 observability seam). */
114
+ warnActionFailed(stateOrNodeId, transitionsTaken, error) {
115
+ addSpanEvent('workflow.action.failed_continue', {
116
+ node: stateOrNodeId,
117
+ transitionsTaken,
118
+ ...(error === undefined ? {} : { error }),
119
+ });
120
+ void this.events?.emit('workflow.action.failed_continue', {
121
+ node: stateOrNodeId,
122
+ transitionsTaken,
123
+ ...(error === undefined ? {} : { error }),
124
+ });
125
+ this.logger.warn('action failed (continuing)', { node: stateOrNodeId, transitionsTaken, error });
126
+ }
127
+ result(status, finalState, transitionsTaken, reason) {
128
+ return {
129
+ runId: this.runId,
130
+ workflowName: this.workflowName,
131
+ mode: this.mode,
132
+ status,
133
+ finalState,
134
+ transitionsTaken,
135
+ ...(reason === undefined ? {} : { reason }),
136
+ };
137
+ }
138
+ runRecord(metadata) {
139
+ return {
140
+ id: this.runId,
141
+ workflow_name: this.workflowName,
142
+ mode: this.mode,
143
+ status: 'running',
144
+ started_at: this.startedAt,
145
+ metadata_json: JSON.stringify(metadata ?? {}),
146
+ completed_at: null,
147
+ };
148
+ }
149
+ }
@@ -1,2 +1,3 @@
1
+ /** SQL DDL for the dual-workflow engine's persistent schema — runs, phase_runs, transition_runs, and workflow_states tables. */
1
2
  export declare const WORKFLOW_ENGINE_SCHEMA_SQL: string;
2
3
  //# sourceMappingURL=schema-sql.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"schema-sql.d.ts","sourceRoot":"","sources":["../src/schema-sql.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,0BAA0B,QA+C/B,CAAC"}
1
+ {"version":3,"file":"schema-sql.d.ts","sourceRoot":"","sources":["../src/schema-sql.ts"],"names":[],"mappings":"AAAA,gIAAgI;AAChI,eAAO,MAAM,0BAA0B,QA+C/B,CAAC"}
@@ -1,3 +1,4 @@
1
+ /** SQL DDL for the dual-workflow engine's persistent schema — runs, phase_runs, transition_runs, and workflow_states tables. */
1
2
  export const WORKFLOW_ENGINE_SCHEMA_SQL = `
2
3
  CREATE TABLE IF NOT EXISTS runs (
3
4
  id TEXT PRIMARY KEY,
package/dist/schema.d.ts CHANGED
@@ -3,6 +3,10 @@ import { z } from 'zod';
3
3
  export declare const ActionDefSchema: z.ZodObject<{
4
4
  kind: z.ZodString;
5
5
  options: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
6
+ onError: z.ZodOptional<z.ZodEnum<{
7
+ fail: "fail";
8
+ continue: "continue";
9
+ }>>;
6
10
  }, z.core.$strip>;
7
11
  /** Zod schema for workflow guard definitions. */
8
12
  export declare const GuardDefSchema: z.ZodObject<{
@@ -19,6 +23,10 @@ export declare const StateMachineWorkflowDefSchema: z.ZodObject<{
19
23
  initialState: z.ZodString;
20
24
  terminalStates: z.ZodOptional<z.ZodArray<z.ZodString>>;
21
25
  iterationBound: z.ZodOptional<z.ZodNumber>;
26
+ defaultOnError: z.ZodOptional<z.ZodEnum<{
27
+ fail: "fail";
28
+ continue: "continue";
29
+ }>>;
22
30
  vars: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
23
31
  env: z.ZodOptional<z.ZodObject<{
24
32
  allow: z.ZodOptional<z.ZodArray<z.ZodString>>;
@@ -29,10 +37,18 @@ export declare const StateMachineWorkflowDefSchema: z.ZodObject<{
29
37
  onEnter: z.ZodOptional<z.ZodArray<z.ZodObject<{
30
38
  kind: z.ZodString;
31
39
  options: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
40
+ onError: z.ZodOptional<z.ZodEnum<{
41
+ fail: "fail";
42
+ continue: "continue";
43
+ }>>;
32
44
  }, z.core.$strip>>>;
33
45
  onExit: z.ZodOptional<z.ZodArray<z.ZodObject<{
34
46
  kind: z.ZodString;
35
47
  options: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
48
+ onError: z.ZodOptional<z.ZodEnum<{
49
+ fail: "fail";
50
+ continue: "continue";
51
+ }>>;
36
52
  }, z.core.$strip>>>;
37
53
  }, z.core.$strict>>;
38
54
  transitions: z.ZodArray<z.ZodObject<{
@@ -56,6 +72,10 @@ export declare const TransitionFlowWorkflowDefSchema: z.ZodObject<{
56
72
  initialNode: z.ZodString;
57
73
  terminalNodes: z.ZodOptional<z.ZodArray<z.ZodString>>;
58
74
  iterationBound: z.ZodOptional<z.ZodNumber>;
75
+ defaultOnError: z.ZodOptional<z.ZodEnum<{
76
+ fail: "fail";
77
+ continue: "continue";
78
+ }>>;
59
79
  vars: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
60
80
  env: z.ZodOptional<z.ZodObject<{
61
81
  allow: z.ZodOptional<z.ZodArray<z.ZodString>>;
@@ -72,6 +92,10 @@ export declare const TransitionFlowWorkflowDefSchema: z.ZodObject<{
72
92
  action: z.ZodOptional<z.ZodObject<{
73
93
  kind: z.ZodString;
74
94
  options: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
95
+ onError: z.ZodOptional<z.ZodEnum<{
96
+ fail: "fail";
97
+ continue: "continue";
98
+ }>>;
75
99
  }, z.core.$strip>>;
76
100
  }, z.core.$strict>>;
77
101
  edges: z.ZodArray<z.ZodObject<{
@@ -94,6 +118,10 @@ export declare const WorkflowDefSchema: z.ZodUnion<readonly [z.ZodObject<{
94
118
  initialState: z.ZodString;
95
119
  terminalStates: z.ZodOptional<z.ZodArray<z.ZodString>>;
96
120
  iterationBound: z.ZodOptional<z.ZodNumber>;
121
+ defaultOnError: z.ZodOptional<z.ZodEnum<{
122
+ fail: "fail";
123
+ continue: "continue";
124
+ }>>;
97
125
  vars: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
98
126
  env: z.ZodOptional<z.ZodObject<{
99
127
  allow: z.ZodOptional<z.ZodArray<z.ZodString>>;
@@ -104,10 +132,18 @@ export declare const WorkflowDefSchema: z.ZodUnion<readonly [z.ZodObject<{
104
132
  onEnter: z.ZodOptional<z.ZodArray<z.ZodObject<{
105
133
  kind: z.ZodString;
106
134
  options: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
135
+ onError: z.ZodOptional<z.ZodEnum<{
136
+ fail: "fail";
137
+ continue: "continue";
138
+ }>>;
107
139
  }, z.core.$strip>>>;
108
140
  onExit: z.ZodOptional<z.ZodArray<z.ZodObject<{
109
141
  kind: z.ZodString;
110
142
  options: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
143
+ onError: z.ZodOptional<z.ZodEnum<{
144
+ fail: "fail";
145
+ continue: "continue";
146
+ }>>;
111
147
  }, z.core.$strip>>>;
112
148
  }, z.core.$strict>>;
113
149
  transitions: z.ZodArray<z.ZodObject<{
@@ -129,6 +165,10 @@ export declare const WorkflowDefSchema: z.ZodUnion<readonly [z.ZodObject<{
129
165
  initialNode: z.ZodString;
130
166
  terminalNodes: z.ZodOptional<z.ZodArray<z.ZodString>>;
131
167
  iterationBound: z.ZodOptional<z.ZodNumber>;
168
+ defaultOnError: z.ZodOptional<z.ZodEnum<{
169
+ fail: "fail";
170
+ continue: "continue";
171
+ }>>;
132
172
  vars: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
133
173
  env: z.ZodOptional<z.ZodObject<{
134
174
  allow: z.ZodOptional<z.ZodArray<z.ZodString>>;
@@ -145,6 +185,10 @@ export declare const WorkflowDefSchema: z.ZodUnion<readonly [z.ZodObject<{
145
185
  action: z.ZodOptional<z.ZodObject<{
146
186
  kind: z.ZodString;
147
187
  options: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
188
+ onError: z.ZodOptional<z.ZodEnum<{
189
+ fail: "fail";
190
+ continue: "continue";
191
+ }>>;
148
192
  }, z.core.$strip>>;
149
193
  }, z.core.$strict>>;
150
194
  edges: z.ZodArray<z.ZodObject<{
@@ -1 +1 @@
1
- {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAyBxB,kDAAkD;AAClD,eAAO,MAAM,eAAe;;;iBAG1B,CAAC;AAEH,iDAAiD;AACjD,eAAO,MAAM,cAAc;;;iBAGzB,CAAC;AAEH,yDAAyD;AACzD,eAAO,MAAM,6BAA6B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAmC7B,CAAC;AAEd,2DAA2D;AAC3D,eAAO,MAAM,+BAA+B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAkC/B,CAAC;AAEd,iEAAiE;AACjE,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;oBAA4E,CAAC"}
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAyBxB,kDAAkD;AAClD,eAAO,MAAM,eAAe;;;;;;;iBAI1B,CAAC;AAEH,iDAAiD;AACjD,eAAO,MAAM,cAAc;;;iBAGzB,CAAC;AAEH,yDAAyD;AACzD,eAAO,MAAM,6BAA6B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAoC7B,CAAC;AAEd,2DAA2D;AAC3D,eAAO,MAAM,+BAA+B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAmC/B,CAAC;AAEd,iEAAiE;AACjE,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;oBAA4E,CAAC"}
package/dist/schema.js CHANGED
@@ -22,6 +22,7 @@ const EnvSchema = z.object({
22
22
  export const ActionDefSchema = z.object({
23
23
  kind: z.string().min(1),
24
24
  options: z.record(z.string(), z.unknown()).optional(),
25
+ onError: z.enum(['fail', 'continue']).optional(),
25
26
  });
26
27
  /** Zod schema for workflow guard definitions. */
27
28
  export const GuardDefSchema = z.object({
@@ -40,6 +41,7 @@ export const StateMachineWorkflowDefSchema = z
40
41
  initialState: z.string().min(1),
41
42
  terminalStates: z.array(z.string().min(1)).optional(),
42
43
  iterationBound: z.number().int().positive().optional(),
44
+ defaultOnError: z.enum(['fail', 'continue']).optional(),
43
45
  vars: VarsSchema.optional(),
44
46
  env: EnvSchema.optional(),
45
47
  states: z.array(z
@@ -73,6 +75,7 @@ export const TransitionFlowWorkflowDefSchema = z
73
75
  initialNode: z.string().min(1),
74
76
  terminalNodes: z.array(z.string().min(1)).optional(),
75
77
  iterationBound: z.number().int().positive().optional(),
78
+ defaultOnError: z.enum(['fail', 'continue']).optional(),
76
79
  vars: VarsSchema.optional(),
77
80
  env: EnvSchema.optional(),
78
81
  nodes: z.array(z
@@ -11,8 +11,13 @@ export declare class StateMachineDriver {
11
11
  constructor(options: StateMachineDriverOptions);
12
12
  /** Run a state-machine workflow to completion or failure. */
13
13
  run(workflow: StateMachineWorkflowDef, options?: WorkflowRunOptions): Promise<WorkflowRunResult>;
14
+ private loop;
15
+ /**
16
+ * Run a state's actions in order. Returns the last action result (retained even
17
+ * when a failure was continued past, so downstream guards can inspect it) plus an
18
+ * `outcome` discriminator: `terminal` (an action declared terminal success),
19
+ * `fail` (a failure under a 'fail' policy — caller must halt), or `completed`.
20
+ */
14
21
  private runActions;
15
- private done;
16
- private fail;
17
22
  }
18
23
  //# sourceMappingURL=state-machine.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"state-machine.d.ts","sourceRoot":"","sources":["../src/state-machine.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,QAAQ,CAAC;AACjD,OAAO,KAAK,EAGR,uBAAuB,EACvB,0BAA0B,EAC1B,kBAAkB,EAElB,iBAAiB,EACpB,MAAM,SAAS,CAAC;AAGjB,yDAAyD;AACzD,MAAM,WAAW,yBAAyB;IACtC,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC;IAClC,QAAQ,CAAC,WAAW,EAAE,0BAA0B,CAAC;CACpD;AAED,wEAAwE;AACxE,qBAAa,kBAAkB;IACf,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,EAAE,yBAAyB;IAE/D,6DAA6D;IACvD,GAAG,CAAC,QAAQ,EAAE,uBAAuB,EAAE,OAAO,GAAE,kBAAuB,GAAG,OAAO,CAAC,iBAAiB,CAAC;YA8G5F,UAAU;YA8BV,IAAI;YAYJ,IAAI;CAYrB"}
1
+ {"version":3,"file":"state-machine.d.ts","sourceRoot":"","sources":["../src/state-machine.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,QAAQ,CAAC;AAEjD,OAAO,KAAK,EAIR,uBAAuB,EACvB,0BAA0B,EAC1B,kBAAkB,EAClB,iBAAiB,EACpB,MAAM,SAAS,CAAC;AAGjB,yDAAyD;AACzD,MAAM,WAAW,yBAAyB;IACtC,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC;IAClC,QAAQ,CAAC,WAAW,EAAE,0BAA0B,CAAC;CACpD;AAED,wEAAwE;AACxE,qBAAa,kBAAkB;IACf,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,EAAE,yBAAyB;IAE/D,6DAA6D;IACvD,GAAG,CAAC,QAAQ,EAAE,uBAAuB,EAAE,OAAO,GAAE,kBAAuB,GAAG,OAAO,CAAC,iBAAiB,CAAC;YAU5F,IAAI;IA6FlB;;;;;OAKG;YACW,UAAU;CA0C3B"}