@orkestrel/workflow 0.0.1
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/LICENSE +21 -0
- package/README.md +45 -0
- package/dist/src/browser/index.d.ts +279 -0
- package/dist/src/browser/index.js +399 -0
- package/dist/src/browser/index.js.map +1 -0
- package/dist/src/core/index.cjs +2805 -0
- package/dist/src/core/index.cjs.map +1 -0
- package/dist/src/core/index.d.cts +3179 -0
- package/dist/src/core/index.d.ts +3179 -0
- package/dist/src/core/index.js +2734 -0
- package/dist/src/core/index.js.map +1 -0
- package/dist/src/server/index.cjs +129 -0
- package/dist/src/server/index.cjs.map +1 -0
- package/dist/src/server/index.d.cts +93 -0
- package/dist/src/server/index.d.ts +93 -0
- package/dist/src/server/index.js +127 -0
- package/dist/src/server/index.js.map +1 -0
- package/package.json +111 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":["#sleep","#table","#snapshots","#context","#phase","#workflow","#recompute","#metadata","#emitter","#status","#result","#transition","#escalate","#record","#tasks","#context","#workflow","#escalateUp","#tasks","#bail","#emitter","#append","#override","#status","#statuses","#force","#emitFor","#recompute","#failure","#phases","#context","#bail","#bailOverride","#phases","#emitter","#created","#updated","#append","#override","#status","#statuses","#force","#emitFor","#recompute","#failure","#abort","#spawn","#handler","#entries","#queue","#emitter","#aborts","#order","#values","#dispatch","#count","#stopped","#started","#running","#drained","#launch","#failure","#collect","#cancel","#settle","#spawn","#results","#functions","#tools","#agents","#scheduler","#workflowTool","#execute","#fold","#cancelled","#halted","#skipFrom","#runPhase","#phaseOf","#stoppable","#completable","#taskOf","#runTask","#taskSignal","#skipping","#skip","#dispatch","#timedOut","#dispatchAgent","#bindWorkflowTool","#runAgent"],"sources":["../../../src/core/Scheduler.ts","../../../src/core/constants.ts","../../../src/core/errors.ts","../../../src/core/helpers.ts","../../../src/core/shapers.ts","../../../src/core/stores/DatabaseWorkflowStore.ts","../../../src/core/stores/MemoryWorkflowStore.ts","../../../src/core/tasks/Task.ts","../../../src/core/tasks/TaskManager.ts","../../../src/core/phases/Phase.ts","../../../src/core/phases/PhaseManager.ts","../../../src/core/Workflow.ts","../../../src/core/Controller.ts","../../../src/core/Runner.ts","../../../src/core/tasks/TaskController.ts","../../../src/core/WorkflowRunner.ts","../../../src/core/factories.ts"],"sourcesContent":["import type { SchedulerInterface, SchedulerOptions } from './types.js'\n\n/**\n * The safe cross-environment cooperative-yield default — a {@link SchedulerInterface}\n * built on `setTimeout` / `clearTimeout` alone, so it runs unchanged in both the\n * browser and Node.\n *\n * @remarks\n * - **Cross-environment.** Uses ONLY `setTimeout` / `clearTimeout` — universally\n * available. It deliberately avoids env-specific fast paths (`setImmediate`,\n * `scheduler.yield`, `requestAnimationFrame`, `node:timers/promises`,\n * `MessageChannel`); those belong to the environment backends, built with the\n * agent loop that consumes them.\n * - **`yield` is a macrotask host-turn, not a microtask.** `yield()` waits on a\n * `setTimeout(0)`, NOT `queueMicrotask`. A microtask drains before the host\n * regains control, so it would not actually let pending I/O, timers, or\n * rendering run — it only defers within the current task. A zero-delay timer is\n * the correct cross-environment \"give the host a turn\".\n * - **Abort-aware.** A pending `yield` / `delay` rejects with `signal.reason` when\n * the signal aborts (the standard `AbortSignal` convention). An already-aborted\n * signal rejects immediately without arming a timer. Either settle path clears\n * the timer and removes the abort listener — no leaked timer, no leaked\n * listener, and no double-settle.\n * - **Priority is accepted but uniform.** `options.priority` is part of the\n * contract, but a `setTimeout`-based default cannot act on urgency, so it treats\n * every priority the same. Environment backends honour it.\n * - **Event-free.** A pure functional primitive — no Emitter, no events.\n *\n * @example\n * ```ts\n * const scheduler = new Scheduler()\n * while (!signal.aborted) {\n * \tdoSomeWork()\n * \tawait scheduler.yield({ signal }) // let the host run between work units\n * }\n * ```\n */\nexport class Scheduler implements SchedulerInterface {\n\t/**\n\t * Yield control back to the host so other tasks (I/O, timers, rendering) can\n\t * run, then resume — a macrotask turn via `setTimeout(0)` (NOT a microtask,\n\t * which would resume before the host regains control).\n\t */\n\tyield(options?: SchedulerOptions): Promise<void> {\n\t\treturn this.#sleep(0, options?.signal)\n\t}\n\n\t/**\n\t * Resume after at least `ms` milliseconds; abort rejects with `signal.reason`.\n\t *\n\t * @remarks\n\t * `ms` should be a non-negative finite number. The primitive stays minimal and\n\t * does no validation: it passes `ms` straight to the host `setTimeout`, which\n\t * clamps a negative value or `NaN` to ~0 — so an out-of-domain `ms` resolves on\n\t * the next host turn rather than throwing.\n\t */\n\tdelay(ms: number, options?: SchedulerOptions): Promise<void> {\n\t\treturn this.#sleep(ms, options?.signal)\n\t}\n\n\t// A single abort-aware `setTimeout` sleep shared by `yield` (ms = 0) and\n\t// `delay`. Resolves after the timer fires; rejects with `signal.reason` if the\n\t// signal is already aborted (no timer armed) or aborts while pending.\n\t//\n\t// The two settle paths are mutually exclusive, and that is load-bearing: each\n\t// path disarms the other before settling. The timer path REMOVES the abort\n\t// listener before it resolves, so a later abort can no longer reach `reject`;\n\t// the abort path CLEARS the timer before it rejects, so the macrotask can no\n\t// longer reach `resolve`. Whichever fires first disarms the other — so the\n\t// promise settles exactly once, with no leaked timer and no leaked listener.\n\t// `{ once: true }` is a backstop against a double-abort, not the guarantee.\n\t#sleep(ms: number, signal?: AbortSignal): Promise<void> {\n\t\tif (signal?.aborted === true) return Promise.reject(signal.reason)\n\t\treturn new Promise<void>((resolve, reject) => {\n\t\t\tconst onAbort = () => {\n\t\t\t\tclearTimeout(handle)\n\t\t\t\treject(signal?.reason)\n\t\t\t}\n\t\t\tconst handle = setTimeout(() => {\n\t\t\t\tsignal?.removeEventListener('abort', onAbort) // load-bearing: prevents a post-resolve reject\n\t\t\t\tresolve()\n\t\t\t}, ms)\n\t\t\tsignal?.addEventListener('abort', onAbort, { once: true })\n\t\t})\n\t}\n}\n","import type {\n\tPhaseStatus,\n\tTaskStatus,\n\tTaskVia,\n\tWorkflowDefinition,\n\tWorkflowStatus,\n\tWorkflowSteps,\n} from './types.js'\n\n// Workflow constants — the centralized data the contract, the derivation helpers,\n// and (later) the entities read. UPPER_SNAKE, `Object.freeze`d, every member\n// exported (AGENTS §5). The status-vocabulary arrays are the runtime source of\n// truth for the §10 unions: compose them with the shipped contracts primitives\n// (`literalOf(...)` for a guard, `literalShape(...)` for a contract) instead of a\n// bespoke guard.\n\n/** The default {@link import('./types.js').WorkflowDefinition.bail} — graceful (continue on a leaf failure). */\nexport const DEFAULT_BAIL = false\n\n/**\n * The three task-form mechanisms (the {@link TaskVia} discriminant), frozen.\n *\n * @remarks\n * The runtime source of truth for the `via` axis — drive the contract's literal\n * shape and any guard from this array rather than repeating the literals.\n */\nexport const TASK_VIAS: readonly TaskVia[] = Object.freeze(['function', 'tool', 'agent'])\n\n/**\n * Every {@link TaskStatus} value, frozen — the lifecycle vocabulary of a task.\n *\n * @remarks\n * Ordered pending → running → terminal (`completed` / `failed` / `skipped` /\n * `stopped`). The source of truth for the union; compose guards / shapes from it.\n */\nexport const TASK_STATUSES: readonly TaskStatus[] = Object.freeze([\n\t'pending',\n\t'running',\n\t'completed',\n\t'failed',\n\t'skipped',\n\t'stopped',\n])\n\n/** Every {@link PhaseStatus} value, frozen — the lifecycle vocabulary of a phase. */\nexport const PHASE_STATUSES: readonly PhaseStatus[] = Object.freeze([\n\t'pending',\n\t'running',\n\t'completed',\n\t'failed',\n\t'skipped',\n\t'stopped',\n])\n\n/** Every {@link WorkflowStatus} value, frozen — the lifecycle vocabulary of a workflow. */\nexport const WORKFLOW_STATUSES: readonly WorkflowStatus[] = Object.freeze([\n\t'pending',\n\t'running',\n\t'completed',\n\t'failed',\n\t'skipped',\n\t'stopped',\n])\n\n/**\n * The {@link TaskStatus} values that are TERMINAL — a task in one of these will\n * not transition further, frozen.\n *\n * @remarks\n * The source of truth behind {@link import('./helpers.js').isTerminalStatus}.\n * `pending` and `running` are the only non-terminal members.\n */\nexport const TERMINAL_TASK_STATUSES: readonly TaskStatus[] = Object.freeze([\n\t'completed',\n\t'failed',\n\t'skipped',\n\t'stopped',\n])\n\n/**\n * The legal {@link TaskStatus} transition graph of the live W-b task state machine —\n * each current status mapped to the statuses it may move to directly, frozen.\n *\n * @remarks\n * The source of truth behind {@link import('./helpers.js').canTransitionTask} and the\n * `TRANSITION` guard ({@link import('./errors.js').WorkflowError}). A `pending` task may\n * `start` (→ `running`), `skip` (→ `skipped`), or `stop` (→ `stopped`); a `running` task\n * may `complete` (→ `completed`), `fail` (→ `failed`), `skip` (→ `skipped`), or `stop`\n * (→ `stopped`). Every terminal status maps to an empty list — a settled task never\n * transitions again. So completing a non-`running` task, or starting a settled one, is\n * rejected.\n */\nexport const TASK_TRANSITIONS: Readonly<Record<TaskStatus, readonly TaskStatus[]>> = Object.freeze({\n\tpending: ['running', 'skipped', 'stopped'],\n\trunning: ['completed', 'failed', 'skipped', 'stopped'],\n\tcompleted: [],\n\tfailed: [],\n\tskipped: [],\n\tstopped: [],\n})\n\n/**\n * The default per-phase task concurrency the {@link import('./factories.js').createWorkflowRunner}\n * runner applies when a {@link import('./types.js').PhaseDefinition} omits its `concurrency`\n * throttle — a large cap that is effectively unbounded for any realistic phase.\n *\n * @remarks\n * The determinism principle fixes that a phase's tasks run CONCURRENTLY; `concurrency` is\n * only an optional resource throttle (max-in-flight). With none declared, the runner runs\n * all of a phase's tasks at once — modelled as this large finite cap so the value flows\n * straight into the substrate {@link import('./types.js').RunnerInterface}'s\n * `concurrency` (which expects a positive integer) without a special unbounded branch. No\n * realistic phase declares enough tasks to reach it, so it behaves as \"run them all\".\n */\nexport const DEFAULT_PHASE_CONCURRENCY = 1_000_000\n\n/**\n * The maximum nesting depth a workflow's `agent` task may spawn into (W-c) — the\n * bound the runner's depth/cycle guard enforces.\n *\n * @remarks\n * The limit lives in ONE place. The `agent` {@link import('./types.js').TaskForm} is\n * bounded by it when the {@link import('./WorkflowRunner.js').WorkflowRunner} resolves a\n * subagent: an agent running at this depth can no longer author + run a nested workflow\n * (that would be depth `MAX_WORKFLOW_DEPTH + 1`), so the over-deep `agent` task is\n * rejected (a typed `DEPTH` `task.fail`). The chain therefore nests workflows down to\n * this depth, and the `agent` task in the depth-`MAX_WORKFLOW_DEPTH` workflow fails.\n */\nexport const MAX_WORKFLOW_DEPTH = 8\n\n/**\n * The name under which the {@link import('./WorkflowRunner.js').WorkflowRunner} BINDS the\n * depth/cycle-aware workflow tool onto a dispatched `agent` task's\n * `AgentContextInterface` (the future `@orkestrel/agent` package, W-c2).\n *\n * @remarks\n * The propagation seam's well-known key: before running an `agent` task, the runner adds a\n * {@link import('./factories.js').createWorkflowTool}-built tool under this name to the\n * resolved agent's `context.tools`, so the subagent can author + run a NESTED workflow\n * (bounded by {@link MAX_WORKFLOW_DEPTH}). A subagent that wants to fan out into a workflow\n * calls this tool by this name; the bound handler runs the nested workflow at depth + 1.\n */\nexport const WORKFLOW_TOOL_NAME = 'workflow'\n\n/**\n * A complete FLAT authoring example — the PRIMARY way a small model authors a workflow\n * through {@link import('./factories.js').createWorkflowTool}: `{ name, steps: [{ name, via }] }`.\n *\n * @remarks\n * Each step becomes a one-task phase, in order; a step's `name` is a REGISTERED behavior name\n * (not a label) and `via` is the execution mechanism. The tool expands this\n * ({@link import('./helpers.js').expandSteps}) into a valid {@link WorkflowDefinition}. It\n * is embedded VERBATIM in {@link WORKFLOW_TOOL_DESCRIPTION} and guarded by a parity test\n * (it must expand to a tree the STRICT contract accepts), so the doc example can never drift.\n */\nexport const WORKFLOW_TOOL_FLAT_EXAMPLE: WorkflowSteps = Object.freeze({\n\tname: 'release',\n\tsteps: Object.freeze([\n\t\tObject.freeze({ name: 'compile', via: 'function' }),\n\t\tObject.freeze({ name: 'publish', via: 'tool' }),\n\t]),\n})\n\n/**\n * A minimal NESTED authoring example — the ADVANCED escape-hatch form a model may use\n * instead of the flat shape: a full {@link WorkflowDefinition}.\n *\n * @remarks\n * The full four-level form, documented in {@link WORKFLOW_TOOL_DESCRIPTION} as the advanced\n * alternative. It is embedded VERBATIM and guarded by a parity test (`createWorkflowContract().is`\n * must accept it), so the doc example can never drift from a valid definition.\n */\nexport const WORKFLOW_TOOL_NESTED_EXAMPLE: WorkflowDefinition = Object.freeze({\n\tid: 'release',\n\tname: 'Release',\n\tphases: Object.freeze([\n\t\tObject.freeze({\n\t\t\tid: 'build',\n\t\t\tname: 'Build',\n\t\t\ttasks: Object.freeze([\n\t\t\t\tObject.freeze({\n\t\t\t\t\tid: 'compile',\n\t\t\t\t\tname: 'Compile',\n\t\t\t\t\trun: Object.freeze({ via: 'function' as const, name: 'compile' }),\n\t\t\t\t}),\n\t\t\t]),\n\t\t}),\n\t]),\n})\n\n/**\n * The DESCRIPTION {@link import('./factories.js').createWorkflowTool} advertises — a\n * multi-line guide that teaches a small model how to author a complete workflow tree.\n *\n * @remarks\n * Presents the SIMPLE flat shape (`{ name, steps: [{ name, via }] }`) as the PRIMARY way with\n * one complete worked example ({@link WORKFLOW_TOOL_FLAT_EXAMPLE}), names the three `via`\n * values + that a step's `name` is a REGISTERED name (not a human label), and documents the full nested\n * {@link WorkflowDefinition} as the ADVANCED form with a minimal example\n * ({@link WORKFLOW_TOOL_NESTED_EXAMPLE}). Both examples are interpolated VERBATIM from the\n * validated constants, so a parity test pins them — the description can never drift from a\n * real, contract-valid example. The `parameters` the tool advertises are the FLAT shape's\n * schema; the nested form is the documented escape-hatch (the tool accepts both).\n */\nexport const WORKFLOW_TOOL_DESCRIPTION = [\n\t'Author and run a workflow (phases run sequentially, the tasks within a phase run concurrently) in one call.',\n\t'',\n\t'SIMPLEST way — a flat list of steps. Each step runs one registered behavior; steps run one after another:',\n\t' { \"name\": \"<workflow name>\", \"steps\": [ { \"name\": \"<registered name>\", \"via\": \"function|tool|agent\" }, ... ] }',\n\t'- a step\\'s \"name\" is a REGISTERED behavior name (a registry key), NOT a human label.',\n\t'- \"via\" is how to run it: \"function\" (the default if omitted), \"tool\", or \"agent\".',\n\t'- the top-level \"name\" (the workflow name) is optional. Ids are filled in for you.',\n\t'Example:',\n\tJSON.stringify(WORKFLOW_TOOL_FLAT_EXAMPLE),\n\t'',\n\t'ADVANCED — the full nested form, for multi-task phases or explicit ids. A workflow has phases; a phase has tasks; a task has a \"run\" of { \"via\", \"name\" }:',\n\tJSON.stringify(WORKFLOW_TOOL_NESTED_EXAMPLE),\n\t'In the nested form you may omit any \"id\"/\"name\" and they are filled in positionally; a provided one is kept.',\n].join('\\n')\n","import type { WorkflowErrorCode } from './types.js'\n\n// AGENTS §12: an illegal state-machine transition, a structurally invalid restore, an\n// over-deep / cyclic nested-workflow dispatch, or a malformed workflow-tool args blob\n// `throw`s a `WorkflowError` carrying a machine-readable `code`, so a `catch` branches\n// on `error.code` instead of parsing the message. The `context` bag names the offending\n// node / status. Optional lookups (`task` / `phase`) return `undefined` — they never throw.\n\n/**\n * An error thrown by the workflow entity + W-c2 recursion layer.\n *\n * @remarks\n * Carries a {@link WorkflowErrorCode} and an optional `context` bag naming the\n * offending node id / status. Thrown for an illegal lifecycle transition\n * (`TRANSITION`), a structurally invalid {@link import('./types.js').WorkflowSnapshot}\n * passed to {@link import('./factories.js').restoreWorkflow} (`RESTORE`), an over-deep /\n * cyclic nested-workflow dispatch (`DEPTH`), and a malformed\n * {@link import('./factories.js').createWorkflowTool} args blob (`TOOL`). On the\n * workflow-tool seam the `DEPTH` / `TOOL` throw is ISOLATED by the\n * `@orkestrel/agent` package's `ToolManager` into the tool result's\n * top-level `error` (AGENTS §14 — the universal tool-handler contract).\n */\nexport class WorkflowError extends Error {\n\treadonly code: WorkflowErrorCode\n\treadonly context?: Readonly<Record<string, unknown>>\n\n\tconstructor(\n\t\tcode: WorkflowErrorCode,\n\t\tmessage: string,\n\t\tcontext?: Readonly<Record<string, unknown>>,\n\t) {\n\t\tsuper(message)\n\t\tthis.name = 'WorkflowError'\n\t\tthis.code = code\n\t\tthis.context = context\n\t}\n}\n\n/**\n * Narrow an unknown caught value to a {@link WorkflowError}.\n *\n * @param value - The value to test (typically a `catch` binding)\n * @returns `true` when `value` is a {@link WorkflowError}\n *\n * @example\n * ```ts\n * try {\n * \ttask.complete('done')\n * } catch (error) {\n * \tif (isWorkflowError(error) && error.code === 'TRANSITION') retry()\n * }\n * ```\n */\nexport function isWorkflowError(value: unknown): value is WorkflowError {\n\treturn value instanceof WorkflowError\n}\n","import type {\n\tDeferredInterface,\n\tLifecycleStatus,\n\tPhaseContext,\n\tPhaseDefinition,\n\tPhaseDerivation,\n\tPhaseDraft,\n\tPhaseSnapshot,\n\tPhaseStatus,\n\tTaskContext,\n\tTaskDefinition,\n\tTaskDraft,\n\tTaskForm,\n\tTaskResult,\n\tTaskSnapshot,\n\tTaskStatus,\n\tWorkflowContext,\n\tWorkflowDefinition,\n\tWorkflowDraft,\n\tWorkflowResult,\n\tWorkflowSnapshot,\n\tWorkflowStatus,\n\tWorkflowStep,\n\tWorkflowSteps,\n} from './types.js'\nimport { isArray, isBoolean, isNumber, isRecord, isString } from '@orkestrel/contract'\nimport { DEFAULT_BAIL, TASK_TRANSITIONS } from './constants.js'\n\n// Workflow derivation helpers — pure, side-effect-free functions (AGENTS §4.3,\n// §14). Every function is exported and unit-tested. The status derivations encode\n// the §10/§14 truth-table logic: a phase status is derived from its tasks'\n// statuses, a workflow status from its phases' statuses UNDER the `bail` policy.\n// Determinism is fixed by design (tasks concurrent, phases sequential), so these\n// derivations are order-insensitive set reductions, never sequencing decisions.\n\n// === Task-form guards (narrow a TaskForm on its `via` discriminant)\n\n/**\n * Narrow a {@link TaskForm} to the `function` form — a task that runs a registered\n * function.\n *\n * @param form - The task form to test\n * @returns `true` when `form.via` is `'function'`\n */\nexport function isFunctionTask(\n\tform: TaskForm,\n): form is { readonly via: 'function'; readonly name: string } {\n\treturn form.via === 'function'\n}\n\n/**\n * Narrow a {@link TaskForm} to the `tool` form — a task that runs a registered tool.\n *\n * @param form - The task form to test\n * @returns `true` when `form.via` is `'tool'`\n */\nexport function isToolTask(\n\tform: TaskForm,\n): form is { readonly via: 'tool'; readonly name: string } {\n\treturn form.via === 'tool'\n}\n\n/**\n * Narrow a {@link TaskForm} to the `agent` form — a task that runs a registered\n * agent (a subagent).\n *\n * @param form - The task form to test\n * @returns `true` when `form.via` is `'agent'`\n */\nexport function isAgentTask(\n\tform: TaskForm,\n): form is { readonly via: 'agent'; readonly name: string } {\n\treturn form.via === 'agent'\n}\n\n// === Ancestry tags (the W-c2 depth/cycle chain identifiers)\n\n/**\n * The ancestry identifier of a workflow run — `workflow:<id>`.\n *\n * @remarks\n * The {@link import('./WorkflowRunner.js').WorkflowRunner}'s cycle guard records one of\n * these per workflow in the current nested run chain (carried on\n * {@link import('./types.js').WorkflowRunOptions.ancestry}). Tagging the bare id keeps a\n * workflow id and an {@link agentTag} agent name in ONE namespaced set without collision,\n * so re-entering a workflow OR an agent already in the chain is a single `includes` check.\n *\n * @param id - The workflow definition's `id`\n * @returns The namespaced ancestry tag (`workflow:<id>`)\n */\nexport function workflowTag(id: string): string {\n\treturn `workflow:${id}`\n}\n\n/**\n * The ancestry identifier of an agent in a run chain — `agent:<name>`.\n *\n * @remarks\n * The agent counterpart of {@link workflowTag}: the runner adds one when it dispatches an\n * `agent` task, and rejects the task (a typed `DEPTH` `task.fail`) when the same tag is\n * already in the ancestry (a re-entry cycle). The `agent:` namespace keeps it distinct\n * from a same-string workflow id.\n *\n * @param name - The agent's registry name (the `agent`-form's `name`)\n * @returns The namespaced ancestry tag (`agent:<name>`)\n */\nexport function agentTag(name: string): string {\n\treturn `agent:${name}`\n}\n\n// === Status predicates\n\n/**\n * Test whether a {@link LifecycleStatus} is TERMINAL — a node in this state will not\n * transition further.\n *\n * @remarks\n * The ONE terminal check across all three tiers (AGENTS §4.4 \"one concept = one word\"):\n * a task, a phase, and a workflow share the same {@link LifecycleStatus} vocabulary, so a\n * single predicate covers them — {@link derivePhaseStatus} and {@link deriveWorkflowStatus}\n * both consult it to tell a settled node from an in-flight one. Terminal: `completed` /\n * `failed` / `skipped` / `stopped`; the only non-terminal states are `pending` and\n * `running`.\n *\n * @param status - The lifecycle status to test (a task / phase / workflow status)\n * @returns `true` when the status is terminal\n */\nexport function isTerminalStatus(status: LifecycleStatus): boolean {\n\treturn (\n\t\tstatus === 'completed' || status === 'failed' || status === 'skipped' || status === 'stopped'\n\t)\n}\n\n// === Status derivation\n\n/**\n * Derive a phase's status from its tasks' statuses (tasks are concurrent, so this\n * is an order-insensitive reduction).\n *\n * @remarks\n * The truth table (most-severe terminal wins; `bail`-agnostic — a phase surfaces a\n * task failure as `failed` so the workflow's `bail` policy can decide):\n * - no tasks ⇒ `pending`.\n * - any task `running`, OR a mix of started-and-unsettled tasks (some non-`pending`\n * but not all terminal) ⇒ `running`.\n * - every task `pending` ⇒ `pending`.\n * - all terminal: any `failed` ⇒ `failed`; else any `stopped` ⇒ `stopped`; else any\n * `completed` ⇒ `completed`; else (all `skipped`) ⇒ `skipped`.\n *\n * So an all-`skipped` phase is `skipped`, an all-`stopped` phase is `stopped`, a\n * phase with completed tasks and some skips is `completed`, and a single failed\n * task makes the phase `failed`.\n *\n * @param tasks - The phase's task statuses, in any order\n * @returns The derived {@link PhaseStatus}\n */\nexport function derivePhaseStatus(tasks: readonly TaskStatus[]): PhaseStatus {\n\tif (tasks.length === 0) return 'pending'\n\tif (tasks.every((status) => status === 'pending')) return 'pending'\n\tif (!tasks.every((status) => isTerminalStatus(status))) return 'running'\n\tif (tasks.some((status) => status === 'failed')) return 'failed'\n\tif (tasks.some((status) => status === 'stopped')) return 'stopped'\n\tif (tasks.some((status) => status === 'completed')) return 'completed'\n\treturn 'skipped'\n}\n\n/**\n * Derive a workflow's status from its phases' {@link PhaseDerivation}s — each phase's status\n * paired with the EFFECTIVE `bail` it ran under (`phase.bail ?? workflow.bail`) — so the\n * failure outcome is PER-PHASE-bail-aware (phases are sequential, but the derivation is an\n * order-insensitive reduction over the settled set).\n *\n * @remarks\n * `bail` is now a per-phase override (AGENTS §4.4), so it is carried on each\n * {@link PhaseDerivation} rather than passed as one scalar. It is the ONLY axis that changes\n * the failure outcome, decided per phase:\n * - **A `failed` phase whose effective `bail` is `true` (halt)** propagates ⇒ the workflow is\n * `failed` (the database-transaction halt) — even when the workflow default is graceful.\n * - **A `failed` phase whose effective `bail` is `false` (graceful)** is DATA, not a workflow\n * failure — it folds into completion like a settled phase. A graceful failed phase NEVER\n * makes the workflow `failed` — even when the workflow default is strict.\n *\n * The rest of the table is shared:\n * - no phases ⇒ `pending`.\n * - any phase `running`, OR a mix of started-and-unsettled phases (some non-`pending`\n * but not all terminal) ⇒ `running`.\n * - every phase `pending` ⇒ `pending`.\n * - all terminal (a `failed` phase counts as terminal here): any `stopped` ⇒ `stopped`; else\n * any `completed` (or any graceful-bail `failed`, folded into completion) ⇒ `completed`;\n * else (all `skipped`) ⇒ `skipped`.\n *\n * @param phases - The workflow's per-phase {@link PhaseDerivation}s (status + effective bail), in any order\n * @returns The derived {@link WorkflowStatus}\n */\nexport function deriveWorkflowStatus(phases: readonly PhaseDerivation[]): WorkflowStatus {\n\tif (phases.length === 0) return 'pending'\n\tif (phases.some((phase) => phase.status === 'failed' && phase.bail)) return 'failed'\n\tif (phases.every((phase) => phase.status === 'pending')) return 'pending'\n\tif (!phases.every((phase) => isTerminalStatus(phase.status))) return 'running'\n\tif (phases.some((phase) => phase.status === 'stopped')) return 'stopped'\n\t// A `completed` phase — or a graceful-bail `failed` phase, folded into completion — makes the\n\t// whole workflow complete.\n\tif (\n\t\tphases.some(\n\t\t\t(phase) => phase.status === 'completed' || (phase.status === 'failed' && !phase.bail),\n\t\t)\n\t) {\n\t\treturn 'completed'\n\t}\n\treturn 'skipped'\n}\n\n// === Task state-machine guards (the W-b transition graph + override)\n\n/**\n * Test whether the live W-b task state machine may move directly from one\n * {@link TaskStatus} to another — the legal-transition guard.\n *\n * @remarks\n * Reads the {@link import('./constants.js').TASK_TRANSITIONS} graph: `true` only when\n * `to` is listed under `from`. A settled (terminal) `from` has no legal targets, so any\n * transition off it is `false`. The W-b `Task` consults this before every transition and\n * throws a `TRANSITION` {@link import('./errors.js').WorkflowError} when it returns `false`.\n *\n * @param from - The task's current status\n * @param to - The status the transition would move it to\n * @returns `true` when the move is legal\n */\nexport function canTransitionTask(from: TaskStatus, to: TaskStatus): boolean {\n\treturn TASK_TRANSITIONS[from].includes(to)\n}\n\n// === Result-tree collection\n\n// === Lineage context builders (the chain carried back UP the tree)\n\n/**\n * Build a {@link WorkflowContext} — the identity every level inherits — from a node's\n * `id` / `name` / optional `description`.\n *\n * @remarks\n * The root of the context chain a live {@link import('./Workflow.js').Workflow} exposes;\n * {@link buildPhaseContext} / {@link buildTaskContext} extend it down the tree. Accepts a\n * structural node (a definition or a snapshot node — both carry the three identity fields).\n *\n * @param node - The node's identity (`id` / `name` / optional `description`)\n * @returns The {@link WorkflowContext}\n */\nexport function buildWorkflowContext(node: WorkflowContext): WorkflowContext {\n\treturn {\n\t\tid: node.id,\n\t\tname: node.name,\n\t\t...(node.description === undefined ? {} : { description: node.description }),\n\t}\n}\n\n/**\n * Build a {@link PhaseContext} — a phase's own identity plus a back-reference to its\n * workflow — from the parent {@link WorkflowContext} and the phase node's identity.\n *\n * @param workflow - The parent workflow context (the lineage pointer UP the tree)\n * @param node - The phase's identity (`id` / `name` / optional `description`)\n * @returns The {@link PhaseContext}\n */\nexport function buildPhaseContext(workflow: WorkflowContext, node: WorkflowContext): PhaseContext {\n\treturn { ...buildWorkflowContext(node), workflow }\n}\n\n/**\n * Build a {@link TaskContext} — a task's own identity plus a back-reference to its phase\n * (and, transitively, its workflow) — from the parent {@link PhaseContext} and the task\n * node's identity.\n *\n * @param phase - The parent phase context (carrying the full lineage UP the tree)\n * @param node - The task's identity (`id` / `name` / optional `description`)\n * @returns The {@link TaskContext}\n */\nexport function buildTaskContext(phase: PhaseContext, node: WorkflowContext): TaskContext {\n\treturn { ...buildWorkflowContext(node), phase }\n}\n\n// === Snapshot boundary guard (AGENTS §14 — narrow an opaque storage read)\n\n/**\n * Narrow an `unknown` to a {@link WorkflowSnapshot} — the AGENTS §14 boundary guard for an\n * UNTRUSTED snapshot read (a storage row a {@link import('./stores/DatabaseWorkflowStore.js').DatabaseWorkflowStore}\n * reads back from its opaque JSON column, a snapshot loaded from disk).\n *\n * @remarks\n * A total guard (it NEVER throws — adversarial input returns `false`, AGENTS §14). It checks the\n * snapshot's SHAPE — `id` / `name` / `status` strings, a `boolean` `bail`, an array of `phases`,\n * `created` / `updated` numbers — enough to safely impose the {@link WorkflowSnapshot} type at a\n * storage boundary WITHOUT a cast. It is complementary to\n * {@link import('./factories.js').assertSnapshot}, which validates the DEEPER invariant (every\n * node's status / override drawn from the lifecycle vocabulary) and THROWS a `RESTORE`\n * {@link import('./errors.js').WorkflowError} — the deep gate a {@link import('./factories.js').restoreWorkflow}\n * applies. A boundary read narrows shape with this guard; a restore validates vocabulary with `assertSnapshot`.\n *\n * @param value - The value to test (an opaque storage read)\n * @returns `true` when `value` has the structural shape of a {@link WorkflowSnapshot}\n */\nexport function isWorkflowSnapshot(value: unknown): value is WorkflowSnapshot {\n\treturn (\n\t\tisRecord(value) &&\n\t\tisString(value.id) &&\n\t\tisString(value.name) &&\n\t\tisString(value.status) &&\n\t\tisBoolean(value.bail) &&\n\t\tisArray(value.phases) &&\n\t\tisNumber(value.created) &&\n\t\tisNumber(value.updated)\n\t)\n}\n\n// === Definition → initial snapshot (the unified construction input)\n\n/**\n * Convert a {@link WorkflowDefinition} into an INITIAL {@link WorkflowSnapshot} — every\n * node `pending`, no results, empty metadata — so the live W-b tree has ONE construction\n * path (snapshot-driven) for both a fresh build and a restore.\n *\n * @remarks\n * The structural fields (`id` / `name` / `description` + the ordered phases / tasks)\n * carry over verbatim; the W-b live tree is the DECLARATIVE state machine, so the\n * execution-only definition fields (per-phase `run` / `concurrency`, per-task `retries` /\n * `timeout`) are intentionally dropped (W-c reads them from the definition when it drives\n * transitions). The `bail` policy carries over — at the workflow tier AND, per phase, the\n * EFFECTIVE policy (`phase.bail ?? workflowBail`) on each {@link PhaseSnapshot} — so the seeded\n * snapshot is self-contained; a fresh seed has no `override`. `created` / `updated` are stamped now.\n * {@link import('./factories.js').createWorkflow} builds from this.\n *\n * The optional `bail` override is the EFFECTIVE workflow policy the tree will run under\n * (`createWorkflow` / the runner resolve `options.bail ?? definition.bail ?? DEFAULT_BAIL` and\n * pass it here), so an `options.bail` override reaches BOTH the workflow tier AND the\n * inheritance default of every phase that declares no `bail` of its own — otherwise the\n * per-phase seeds would silently ignore the override. Omitted ⇒ the definition's own `bail`\n * (defaulting to the graceful {@link import('./constants.js').DEFAULT_BAIL}).\n *\n * @param definition - The workflow definition to seed from\n * @param bail - The EFFECTIVE workflow bail to seed both tiers with (defaults to the definition's)\n * @returns An initial, all-`pending` {@link WorkflowSnapshot}\n */\nexport function definitionToSnapshot(\n\tdefinition: WorkflowDefinition,\n\tbail?: boolean,\n): WorkflowSnapshot {\n\tconst now = Date.now()\n\t// The effective workflow-level policy each phase inherits when it declares no `bail` of its own\n\t// — the supplied override (an `options.bail`) when given, else the definition's own default. The\n\t// source of the per-phase effective policy persisted on every PhaseSnapshot.\n\tconst workflowBail = bail ?? definition.bail ?? DEFAULT_BAIL\n\treturn {\n\t\tid: definition.id,\n\t\tname: definition.name,\n\t\t...(definition.description === undefined ? {} : { description: definition.description }),\n\t\tstatus: 'pending',\n\t\tbail: workflowBail,\n\t\tphases: definition.phases.map((phase) => phaseDefinitionToSnapshot(phase, workflowBail)),\n\t\tcreated: now,\n\t\tupdated: now,\n\t}\n}\n\n/**\n * Convert one {@link import('./types.js').PhaseDefinition} into an initial, all-`pending`\n * {@link PhaseSnapshot} — the per-phase step of {@link definitionToSnapshot}.\n *\n * @remarks\n * The snapshot persists the EFFECTIVE failure policy this phase runs under: the phase's own\n * `bail` when it declares one, else the `workflowBail` it inherits — so a restore reinstates\n * the same per-phase policy without a silent default (`effectiveBail = phase.bail ?? workflowBail`).\n *\n * @param phase - The phase definition to seed from\n * @param workflowBail - The workflow-level `bail` default the phase inherits when it declares none\n * @returns An initial {@link PhaseSnapshot}\n */\nexport function phaseDefinitionToSnapshot(\n\tphase: WorkflowDefinition['phases'][number],\n\tworkflowBail: boolean,\n): PhaseSnapshot {\n\treturn {\n\t\tid: phase.id,\n\t\tname: phase.name,\n\t\t...(phase.description === undefined ? {} : { description: phase.description }),\n\t\tstatus: 'pending',\n\t\tbail: phase.bail ?? workflowBail,\n\t\ttasks: phase.tasks.map((task) => taskDefinitionToSnapshot(task)),\n\t}\n}\n\n/**\n * Convert one {@link import('./types.js').TaskDefinition} into an initial, `pending`\n * {@link TaskSnapshot} — the per-task leaf step of {@link definitionToSnapshot} (no\n * result yet, empty metadata).\n *\n * @param task - The task definition to seed from\n * @returns An initial {@link TaskSnapshot}\n */\nexport function taskDefinitionToSnapshot(\n\ttask: WorkflowDefinition['phases'][number]['tasks'][number],\n): TaskSnapshot {\n\treturn {\n\t\tid: task.id,\n\t\tname: task.name,\n\t\t...(task.description === undefined ? {} : { description: task.description }),\n\t\tstatus: 'pending',\n\t\tmetadata: {},\n\t}\n}\n\n/**\n * Flatten a nested list of per-phase {@link TaskResult} lists into one positional list\n * — the workflow tier of the result tree, built from each phase's `results()`.\n *\n * @remarks\n * Pure and order-preserving: phases in order, each phase's task results in order. The\n * W-b `Workflow.results()` calls this over its phases' `results()`; a phase's own\n * `results()` is the per-phase list this consumes.\n *\n * @param phases - The per-phase result lists, in phase order\n * @returns One flattened {@link TaskResult} list, in positional order\n */\nexport function collectResults(phases: readonly (readonly TaskResult[])[]): readonly TaskResult[] {\n\treturn phases.flat()\n}\n\n// === Workflow-tool result mapping (W-c2 — WorkflowResult → the handler's summary value)\n\n/**\n * Summarize a terminal {@link WorkflowResult} into the PLAIN value a\n * {@link import('./factories.js').createWorkflowTool} handler returns on success.\n *\n * @remarks\n * This is the run summary the handler returns DIRECTLY — NOT a `ToolResult` (the future `@orkestrel/agent` package).\n * The handler conforms to the universal tool-handler contract (AGENTS §14): it returns the plain value\n * (and throws on failure), so the `@orkestrel/agent` package's `ToolManager` performs\n * the ONE canonical wrap (`{ id, name, value }`) and the model reads exactly this summary — once,\n * identically — over BOTH the agent loop and MCP. The summary is LEAN: the workflow's terminal `status`\n * and the COUNT of settled task results — enough for a caller / model to react without serializing the\n * whole live tree. (It carries no synthetic `id` / `name`: a tool handler has no call id; the manager\n * supplies the canonical envelope's identity.)\n *\n * @param result - The terminal {@link WorkflowResult} the run produced\n * @returns The plain success summary — `{ status, count }`\n */\nexport function workflowToolSummary(\n\tresult: WorkflowResult,\n): Readonly<{ status: WorkflowStatus; count: number }> {\n\treturn { status: result.status, count: result.results.length }\n}\n\n// === Draft completion + flat-steps expansion (the tool's LENIENT authoring surfaces)\n//\n// Pure, deterministic synthesis that turns a WIDENED authoring form into a strict\n// `WorkflowDefinition`. They auto-fill only OMITTED identity (a provided id/name is\n// preserved verbatim; an explicitly-empty `id: ''` is rejected UPSTREAM by the draft\n// contract, never reached here), so a small model can author a complete tree without\n// emitting the six required `id`/`name` strings. The factory re-validates the result\n// against the STRICT `createWorkflowContract().is` gate before running (soundness).\n\n/**\n * Complete a {@link WorkflowDraft} into a strict {@link WorkflowDefinition} — synthesize\n * any MISSING `id` deterministically + positionally, and default any MISSING `name` to\n * its (now-resolved) `id`.\n *\n * @remarks\n * The positional id scheme is stable and human-legible: the workflow is `wf`, phase `i`\n * is `phase-<i>`, and task `j` of that phase is `<phaseId>-task-<j>` (so a provided phase\n * id flows into its tasks' synthesized ids). A PROVIDED `id` / `name` at any level is kept\n * VERBATIM — synthesis touches only the omitted ones. A missing `name` defaults to the\n * resolved `id` (never the other way round), so the result always has both. `run`,\n * `description`, the per-phase `concurrency` / `bail`, the per-task `retries` / `timeout`, and\n * the workflow `bail` carry over unchanged. The result is a complete\n * {@link WorkflowDefinition}; the caller still validates it against the STRICT contract.\n *\n * @param draft - The draft workflow (id/name optional at all three levels)\n * @returns A complete {@link WorkflowDefinition} with every id/name filled\n */\nexport function completeDraft(draft: WorkflowDraft): WorkflowDefinition {\n\tconst id = draft.id ?? 'wf'\n\treturn {\n\t\tid,\n\t\tname: draft.name ?? id,\n\t\t...(draft.description === undefined ? {} : { description: draft.description }),\n\t\tphases: draft.phases.map((phase, index) => completePhaseDraft(phase, index)),\n\t\t...(draft.bail === undefined ? {} : { bail: draft.bail }),\n\t}\n}\n\n/**\n * Complete one {@link PhaseDraft} into a strict {@link PhaseDefinition} — the per-phase\n * step of {@link completeDraft} (phase `index` → `phase-<index>` when its id is omitted).\n *\n * @param phase - The draft phase\n * @param index - The phase's positional index in the workflow\n * @returns A complete {@link PhaseDefinition}\n */\nexport function completePhaseDraft(phase: PhaseDraft, index: number): PhaseDefinition {\n\tconst id = phase.id ?? `phase-${index}`\n\treturn {\n\t\tid,\n\t\tname: phase.name ?? id,\n\t\t...(phase.description === undefined ? {} : { description: phase.description }),\n\t\ttasks: phase.tasks.map((task, taskIndex) => completeTaskDraft(task, id, taskIndex)),\n\t\t...(phase.concurrency === undefined ? {} : { concurrency: phase.concurrency }),\n\t\t...(phase.bail === undefined ? {} : { bail: phase.bail }),\n\t}\n}\n\n/**\n * Complete one {@link TaskDraft} into a strict {@link TaskDefinition} — the per-task leaf\n * step of {@link completeDraft} (task `index` of phase `<phaseId>` → `<phaseId>-task-<index>`\n * when its id is omitted).\n *\n * @param task - The draft task\n * @param phaseId - The (resolved) parent phase id, so the synthesized task id nests under it\n * @param index - The task's positional index within its phase\n * @returns A complete {@link TaskDefinition}\n */\nexport function completeTaskDraft(task: TaskDraft, phaseId: string, index: number): TaskDefinition {\n\tconst id = task.id ?? `${phaseId}-task-${index}`\n\treturn {\n\t\tid,\n\t\tname: task.name ?? id,\n\t\t...(task.description === undefined ? {} : { description: task.description }),\n\t\trun: task.run,\n\t\t...(task.retries === undefined ? {} : { retries: task.retries }),\n\t\t...(task.timeout === undefined ? {} : { timeout: task.timeout }),\n\t}\n}\n\n/**\n * Expand a flat {@link WorkflowSteps} blob into a strict {@link WorkflowDefinition} — each\n * step becomes a one-task phase, IN ORDER.\n *\n * @remarks\n * The expansion of the tool's ADVERTISED surface (AGENTS §21 — the simplest form a small\n * model can author). Each {@link WorkflowStep} maps to a phase holding exactly one task:\n * the step's `name` becomes the task's `run.name`, and its `via` becomes the task's `run.via`\n * (defaulting to `'function'` when omitted). Ids/names are auto-filled positionally — it\n * builds an ids-omitted {@link WorkflowDraft} and delegates to {@link completeDraft}, so the\n * two lenient surfaces share ONE synthesis path (step `i` → phase `phase-<i>`, its task\n * `phase-<i>-task-0`). The optional `name` becomes the workflow's `name`. The result is a\n * complete definition the caller validates against the STRICT contract before running.\n *\n * @param flat - The flat steps blob (`{ name?, steps: [{ name, via? }] }`)\n * @returns A complete {@link WorkflowDefinition} (one one-task phase per step)\n */\nexport function expandSteps(flat: WorkflowSteps): WorkflowDefinition {\n\treturn completeDraft({\n\t\t...(flat.name === undefined ? {} : { name: flat.name }),\n\t\tphases: flat.steps.map((step) => ({\n\t\t\ttasks: [{ run: stepToForm(step) }],\n\t\t})),\n\t})\n}\n\n/**\n * Convert one flat {@link WorkflowStep} into a {@link TaskForm} — `name` → the form's `name`,\n * `via` → the form's discriminant (defaulting to `'function'`).\n *\n * @param step - The flat step\n * @returns The {@link TaskForm} the step's task runs\n */\nexport function stepToForm(step: WorkflowStep): TaskForm {\n\treturn { via: step.via ?? 'function', name: step.name }\n}\n\n/**\n * Create a {@link DeferredInterface} — a promise whose settlement is driven\n * externally, so a caller can resolve/reject it from outside the executor.\n *\n * @typeParam T - The value the deferred promise resolves\n * @returns A deferred `promise` plus its `resolve` / `reject`\n */\nexport function createDeferred<T>(): DeferredInterface<T> {\n\tlet resolve: (value: T) => void = () => {}\n\tlet reject: (reason: unknown) => void = () => {}\n\tconst promise = new Promise<T>((res, rej) => {\n\t\tresolve = res\n\t\treject = rej\n\t})\n\treturn { promise, resolve, reject }\n}\n","import {\n\tarrayShape,\n\tintegerShape,\n\tliteralShape,\n\tobjectShape,\n\toptionalShape,\n\tstringShape,\n\tunionShape,\n} from '@orkestrel/contract'\n\n// Workflow contract shapes — the shape VALUES the contract (factories.ts) compiles\n// into the four lockstep outputs (JSON Schema + guard + parser + generator). These\n// shapes MUST agree with the hand-written definition interfaces (types.ts), which\n// are the source of truth (AGENTS §14): a valid `WorkflowDefinition` is accepted by\n// the compiled `is` / `parse`, and the seeded `generate` produces a valid one.\n//\n// The definition interfaces stay hand-written rather than `Infer`-derived from\n// these shapes — the databases module already hit TS2589 on nested `objectShape`\n// generics, and this tree nests three levels (workflow → phase → task → form), so\n// the shapes are consumed as plain `ContractShape` runtime descriptors and the\n// contract is typed `ContractInterface<WorkflowDefinition>` at the factory.\n//\n// Per-field `description`s ride INSIDE the advertised JSON Schema (compilers.ts\n// `compileSchema` emits a shape's `description` verbatim), so a small model authoring\n// a tree through `createWorkflowTool` gets field-level guidance — especially on the\n// `via` discriminant and the `run` union, which would otherwise be bare `enum`s with\n// zero hint. The guidance is advisory metadata only: it never changes what the guard /\n// parser accept (the contract stays byte-for-byte strict).\n\n// The description-carrying `via` discriminant + `bail` toggle ride on the shared\n// `literalShape` (the `@orkestrel/contract` module) — a described single-value literal\n// is just `literalShape([value], { description })`, so no module-local helper is needed.\n\n/**\n * The shape of a {@link import('./types.js').TaskForm} — a descriptive tagged union\n * over the three execution mechanisms, discriminated by the `via` literal (never a\n * bare `kind`; AGENTS §4.4). Each variant pairs the `via` discriminant with a `name`\n * (the registry key for the behavior).\n *\n * @remarks\n * The union and each `via` literal + `name` carry a `description` so the emitted JSON\n * Schema spells out what the discriminant means and that `name` is a REGISTERED key\n * (not a human label) — the field-level guidance a small model needs to fill `run`.\n */\nexport const taskFormShape = unionShape(\n\tobjectShape({\n\t\tvia: literalShape(['function'], { description: 'Run a registered workflow FUNCTION by name.' }),\n\t\tname: stringShape({\n\t\t\tmin: 1,\n\t\t\tdescription: 'The registered function name to invoke (a registry key, not a label).',\n\t\t}),\n\t}),\n\tobjectShape({\n\t\tvia: literalShape(['tool'], { description: 'Run a registered TOOL by name.' }),\n\t\tname: stringShape({\n\t\t\tmin: 1,\n\t\t\tdescription: 'The registered tool name to invoke (a registry key, not a label).',\n\t\t}),\n\t}),\n\tobjectShape({\n\t\tvia: literalShape(['agent'], { description: 'Run a registered AGENT (a subagent) by name.' }),\n\t\tname: stringShape({\n\t\t\tmin: 1,\n\t\t\tdescription: 'The registered agent name to invoke (a registry key, not a label).',\n\t\t}),\n\t}),\n)\n\n/**\n * The shape of a {@link import('./types.js').TaskDefinition} — identity plus the\n * behavior reference ({@link taskFormShape}). `description` is optional prose.\n */\nexport const taskShape = objectShape({\n\tid: stringShape({ min: 1, description: 'Unique task id within its phase.' }),\n\tname: stringShape({ min: 1, description: 'Human-readable task name.' }),\n\tdescription: optionalShape(stringShape({ description: 'Optional task description.' })),\n\trun: taskFormShape,\n\tretries: optionalShape(\n\t\tintegerShape({\n\t\t\tmin: 0,\n\t\t\tdescription:\n\t\t\t\t'Extra attempts after the first on failure; overrides the phase default. Omitted means none.',\n\t\t}),\n\t),\n\ttimeout: optionalShape(\n\t\tintegerShape({\n\t\t\tmin: 0,\n\t\t\tdescription:\n\t\t\t\t'Per-attempt deadline in milliseconds; overrides the phase default. Omitted means no deadline.',\n\t\t}),\n\t),\n})\n\n/**\n * The shape of a {@link import('./types.js').PhaseDefinition} — identity, its ordered\n * {@link taskShape} tasks, and an optional positive-integer `concurrency` throttle\n * (max tasks in flight; omitted ⇒ unbounded).\n */\nexport const phaseShape = objectShape({\n\tid: stringShape({ min: 1, description: 'Unique phase id within the workflow.' }),\n\tname: stringShape({ min: 1, description: 'Human-readable phase name.' }),\n\tdescription: optionalShape(stringShape({ description: 'Optional phase description.' })),\n\ttasks: arrayShape(taskShape, { description: 'The phase tasks; they run CONCURRENTLY.' }),\n\tconcurrency: optionalShape(\n\t\tintegerShape({\n\t\t\tmin: 1,\n\t\t\tdescription: 'Max tasks in flight at once (a resource throttle); omitted means unbounded.',\n\t\t}),\n\t),\n\tbail: optionalShape(\n\t\tliteralShape([true, false], {\n\t\t\tdescription: 'Per-phase failure-policy override; omitted inherits the workflow bail.',\n\t\t}),\n\t),\n})\n\n/**\n * The shape of a {@link import('./types.js').WorkflowDefinition} — the contract root:\n * identity, its ordered {@link phaseShape} phases, and the optional `bail` boolean\n * failure policy (the literal pair `true`/`false`, the runtime mirror of the boolean\n * toggle; omitted ⇒ the graceful default).\n */\nexport const workflowShape = objectShape({\n\tid: stringShape({ min: 1, description: 'Unique workflow id.' }),\n\tname: stringShape({ min: 1, description: 'Human-readable workflow name.' }),\n\tdescription: optionalShape(stringShape({ description: 'Optional workflow description.' })),\n\tphases: arrayShape(phaseShape, {\n\t\tdescription: 'The workflow phases; they run SEQUENTIALLY, in order.',\n\t}),\n\tbail: optionalShape(\n\t\tliteralShape([true, false], {\n\t\t\tdescription:\n\t\t\t\t'Failure policy: false (default) continues gracefully, true halts on the first failure.',\n\t\t}),\n\t),\n})\n\n// === Draft + flat-steps shapes (the tool's LENIENT authoring surfaces)\n//\n// These shapes are NOT part of the canonical `WorkflowDefinition` contract — they are\n// the WIDENED authoring surfaces `createWorkflowTool` accepts so a small model can\n// author a complete tree without emitting the full strict form. Both converge on the\n// STRICT `createWorkflowContract().is` gate after expansion/completion (factories.ts),\n// so soundness is preserved: the canonical contract stays unchanged and strict.\n\n/**\n * The shape of a TASK in a draft workflow — identical to {@link taskShape} EXCEPT `id`\n * and `name` are OPTIONAL (the tool synthesizes any missing one positionally).\n *\n * @remarks\n * A PROVIDED `id` / `name` still carries `minLength: 1`, so an explicitly-empty `id: ''`\n * is INVALID (rejected by the draft contract), never auto-filled — keeping \"garbage\"\n * distinct from \"omitted\". `run` stays required.\n */\nexport const taskDraftShape = objectShape({\n\tid: optionalShape(stringShape({ min: 1, description: 'Task id; auto-filled when omitted.' })),\n\tname: optionalShape(\n\t\tstringShape({ min: 1, description: 'Task name; defaults to the id when omitted.' }),\n\t),\n\tdescription: optionalShape(stringShape({ description: 'Optional task description.' })),\n\trun: taskFormShape,\n\tretries: optionalShape(\n\t\tintegerShape({\n\t\t\tmin: 0,\n\t\t\tdescription:\n\t\t\t\t'Extra attempts after the first on failure; overrides the phase default. Omitted means none.',\n\t\t}),\n\t),\n\ttimeout: optionalShape(\n\t\tintegerShape({\n\t\t\tmin: 0,\n\t\t\tdescription:\n\t\t\t\t'Per-attempt deadline in milliseconds; overrides the phase default. Omitted means no deadline.',\n\t\t}),\n\t),\n})\n\n/**\n * The shape of a PHASE in a draft workflow — identical to {@link phaseShape} EXCEPT\n * `id` and `name` are OPTIONAL, and its tasks are {@link taskDraftShape}s.\n */\nexport const phaseDraftShape = objectShape({\n\tid: optionalShape(stringShape({ min: 1, description: 'Phase id; auto-filled when omitted.' })),\n\tname: optionalShape(\n\t\tstringShape({ min: 1, description: 'Phase name; defaults to the id when omitted.' }),\n\t),\n\tdescription: optionalShape(stringShape({ description: 'Optional phase description.' })),\n\ttasks: arrayShape(taskDraftShape, { description: 'The phase tasks; they run CONCURRENTLY.' }),\n\tconcurrency: optionalShape(\n\t\tintegerShape({\n\t\t\tmin: 1,\n\t\t\tdescription: 'Max tasks in flight at once (a resource throttle); omitted means unbounded.',\n\t\t}),\n\t),\n\tbail: optionalShape(\n\t\tliteralShape([true, false], {\n\t\t\tdescription: 'Per-phase failure-policy override; omitted inherits the workflow bail.',\n\t\t}),\n\t),\n})\n\n/**\n * The shape of a DRAFT workflow — identical to {@link workflowShape} EXCEPT `id` and\n * `name` are OPTIONAL at all three levels (workflow / phase / task), so a small model\n * can omit the six identity strings and let the tool synthesize them positionally.\n *\n * @remarks\n * The lenient counterpart {@link import('./factories.js').createWorkflowDraftContract}\n * compiles. `run` stays required; a provided `id` / `name` still has `minLength: 1` (so an\n * explicitly-empty `id: ''` is REJECTED, not auto-filled). After\n * {@link import('./helpers.js').completeDraft} fills the missing ids/names, the result is\n * validated against the STRICT {@link import('./factories.js').createWorkflowContract} gate\n * before running.\n */\nexport const workflowDraftShape = objectShape({\n\tid: optionalShape(stringShape({ min: 1, description: 'Workflow id; auto-filled when omitted.' })),\n\tname: optionalShape(\n\t\tstringShape({ min: 1, description: 'Workflow name; defaults to the id when omitted.' }),\n\t),\n\tdescription: optionalShape(stringShape({ description: 'Optional workflow description.' })),\n\tphases: arrayShape(phaseDraftShape, {\n\t\tdescription: 'The workflow phases; they run SEQUENTIALLY, in order.',\n\t}),\n\tbail: optionalShape(\n\t\tliteralShape([true, false], {\n\t\t\tdescription:\n\t\t\t\t'Failure policy: false (default) continues gracefully, true halts on the first failure.',\n\t\t}),\n\t),\n})\n\n/**\n * The shape of ONE flat step — `{ name, via? }` — the building block of\n * {@link workflowStepsShape}.\n *\n * @remarks\n * `name` is the REGISTERED behavior name the step runs (it becomes the task's `run.name`);\n * `via` is the optional execution mechanism (defaults to `'function'` when omitted). The\n * tool expands each step into a one-task phase, in order\n * ({@link import('./helpers.js').expandSteps}).\n */\nexport const stepShape = objectShape({\n\tname: stringShape({\n\t\tmin: 1,\n\t\tdescription: 'The registered behavior name this step runs (becomes the task run.name).',\n\t}),\n\tvia: optionalShape(\n\t\tliteralShape(['function', 'tool', 'agent'], {\n\t\t\tdescription: 'How to run it: function (default), tool, or agent.',\n\t\t}),\n\t),\n})\n\n/**\n * The FLAT authoring shape `createWorkflowTool` advertises as its `parameters` — the\n * simplest surface a small model can fill: `{ name?, steps: [{ name, via? }] }`.\n *\n * @remarks\n * The deliberately-reduced surface (AGENTS §21): a flat ordered list of steps, each a\n * `{ name, via? }`. The tool EXPANDS it ({@link import('./helpers.js').expandSteps}) into a\n * full {@link import('./types.js').WorkflowDefinition} — one one-task phase per step, in\n * order — then validates against the STRICT\n * {@link import('./factories.js').createWorkflowContract} gate. The full nested form is\n * STILL accepted by the tool (it branches on the args' shape) and is documented as the\n * advanced escape-hatch in the tool's description — but THIS is what `parameters` advertises.\n */\nexport const workflowStepsShape = objectShape({\n\tname: optionalShape(stringShape({ min: 1, description: 'Optional workflow name.' })),\n\tsteps: arrayShape(stepShape, {\n\t\tdescription: 'The ordered steps to run, one after another (each becomes a one-task phase).',\n\t}),\n})\n","import type { TableInterface } from '@orkestrel/database'\nimport type { WorkflowSnapshot, WorkflowSnapshotRow, WorkflowStoreInterface } from '../types.js'\nimport { isWorkflowSnapshot } from '../helpers.js'\n\n/**\n * A {@link WorkflowStoreInterface} backed by one table of the `databases` layer — a\n * workflow's durable run-state IS a row, so persistence reduces to keyed point-access\n * (`get` / `set` / `delete`) over a `TableInterface`, the driver-pluggable twin of the\n * plain-`Map` {@link import('./MemoryWorkflowStore.js').MemoryWorkflowStore}.\n *\n * @remarks\n * The store is driver-agnostic: it holds a single {@link TableInterface} whose backend\n * (memory, JSON, SQLite, IndexedDB) is chosen by whoever builds it (the factories), so a\n * JSON / SQLite / IndexedDB backend swaps in WITHOUT touching the runner or the entity tree\n * — the same seam as `@orkestrel/queue`'s `DatabaseQueueStore`.\n * The driver defaults to memory ({@link import('../factories.js').createDatabaseWorkflowStore}\n * passes `createMemoryDriver()`), so it ALSO works in memory out of the box; you opt into the\n * durable plumbing by passing a JSON / SQLite / IndexedDB driver.\n *\n * The {@link WorkflowSnapshot} is stored as ONE OPAQUE JSON COLUMN — the table is a row of\n * `{ id; snapshot }` ({@link WorkflowSnapshotRow}), the snapshot the whole JSON blob (a `rawShape`\n * column the factory builds) — exactly as `DatabaseQueueStore` stores its `input`. The snapshot is\n * already a COMPLETE, self-contained, pure-JSON payload, so storing it whole is lossless AND\n * sidesteps a TS2589 instantiation-depth blow-up: a structured multi-column table would force the\n * contract to `Infer` the deeply-nested snapshot shape (workflow → phases → tasks → results),\n * tripping the compiler — one JSON column keeps the row type flat (`snapshot` reads back as `unknown`).\n *\n * - **`set(snapshot)` upserts under the snapshot's OWN `id`** (no separate id param) — it writes\n * the row `{ id: snapshot.id, snapshot }`.\n * - **`get(id)` resolves the stored snapshot for an id**, narrowing the opaque JSON column back to\n * a {@link WorkflowSnapshot} ({@link import('../helpers.js').isWorkflowSnapshot} — the AGENTS §14\n * boundary narrow for an untrusted storage read), or `undefined` if none is stored.\n * - **`delete(id)` drops a snapshot by id**; an absent id is a no-op (no throw).\n *\n * UNLIKE the server package's `SessionStoreInterface` there is NO\n * idle-TTL / eviction — a persisted run-state is durable orchestration state that lives until an\n * explicit `delete`. The public surface is EXACTLY `get` / `set` / `delete` — no extra members (the\n * §22 method bijection with {@link WorkflowStoreInterface}). Restore stays a caller concern: read a\n * snapshot back and rebuild the live tree with {@link import('../factories.js').restoreWorkflow}.\n *\n * @example\n * ```ts\n * import { createDatabaseWorkflowStore, createMemoryDriver, createWorkflow, restoreWorkflow } from '@src/core'\n *\n * const store = createDatabaseWorkflowStore(createMemoryDriver()) // a durable driver swaps in here\n * const workflow = createWorkflow(definition)\n * await store.set(workflow.snapshot()) // persist the run state (one JSON column)\n * const snapshot = await store.get(definition.id)\n * const restored = snapshot && restoreWorkflow(snapshot) // an identical live tree\n * await store.delete(definition.id) // drop it\n * ```\n */\nexport class DatabaseWorkflowStore implements WorkflowStoreInterface {\n\treadonly #table: TableInterface<WorkflowSnapshotRow>\n\n\t/**\n\t * Wrap a table as a workflow store.\n\t *\n\t * @param table - The {@link TableInterface} holding the snapshots — its row is the\n\t * {@link WorkflowSnapshotRow} `{ id; snapshot }` shape (the snapshot one opaque JSON column)\n\t */\n\tconstructor(table: TableInterface<WorkflowSnapshotRow>) {\n\t\tthis.#table = table\n\t}\n\n\t/** Resolve the persisted snapshot for `id`, narrowing the opaque JSON column back to a `WorkflowSnapshot`. */\n\tasync get(id: string): Promise<WorkflowSnapshot | undefined> {\n\t\tconst row = await this.#table.get(id)\n\t\tif (row === undefined) return undefined\n\t\t// The snapshot crosses back as an untrusted storage read (a structured clone / a JSON\n\t\t// row), so narrow the opaque JSON column with the boundary guard rather than a cast\n\t\t// (AGENTS §14); a malformed blob resolves `undefined`, never a broken tree.\n\t\treturn isWorkflowSnapshot(row.snapshot) ? row.snapshot : undefined\n\t}\n\n\t/** Insert or replace under the snapshot's OWN `id` (no separate id param) — the row is `{ id, snapshot }`. */\n\tasync set(snapshot: WorkflowSnapshot): Promise<void> {\n\t\tawait this.#table.set({ id: snapshot.id, snapshot })\n\t}\n\n\t/** Drop a snapshot by id; an absent id is a no-op (no throw). */\n\tasync delete(id: string): Promise<void> {\n\t\tawait this.#table.remove(id)\n\t}\n}\n","import type { WorkflowSnapshot, WorkflowStoreInterface } from '../types.js'\n\n/**\n * The in-memory {@link WorkflowStoreInterface} — a process-lifetime `Map` of\n * {@link WorkflowSnapshot}s keyed by workflow id, the DEFAULT store\n * {@link import('../factories.js').createMemoryWorkflowStore} builds.\n *\n * @remarks\n * A plain `Map<string, WorkflowSnapshot>` (AGENTS §21 — the snapshot is already pure,\n * self-contained JSON, so no encoding is needed for the memory tier). UNLIKE the server\n * package's `SessionStoreInterface`'s memory store there is\n * NO idle-TTL and NO eviction: a persisted workflow run-state is durable orchestration state\n * that lives until an explicit `delete`, never silently aging out (a run that vanished\n * mid-flight would be a silent data loss, not a freed session). A durable backend (JSON /\n * SQLite / IndexedDB) swaps in through the SAME interface without touching the runner or the\n * entity tree — its driver-pluggable twin is\n * {@link import('./DatabaseWorkflowStore.js').DatabaseWorkflowStore} (the snapshot as one opaque\n * JSON column), exactly as `@orkestrel/queue`'s `MemoryQueueStore`\n * twins `DatabaseQueueStore`.\n *\n * - **`get` resolves the persisted snapshot for an id**, or `undefined` if none is stored.\n * - **`set` inserts / replaces under the snapshot's OWN `id`** (no separate id param).\n * - **`delete` drops a snapshot by id**; an absent id is a no-op (no throw).\n *\n * The public surface is EXACTLY `get` / `set` / `delete` — no extra members (the §22 method\n * bijection with {@link WorkflowStoreInterface}). Restore is a caller concern: read a snapshot\n * back and rebuild the live tree with {@link import('../factories.js').restoreWorkflow}.\n *\n * @example\n * ```ts\n * import { createMemoryWorkflowStore, createWorkflow, restoreWorkflow } from '@src/core'\n *\n * const store = createMemoryWorkflowStore()\n * const workflow = createWorkflow(definition)\n * await store.set(workflow.snapshot()) // persist the run state\n * const snapshot = await store.get(definition.id)\n * const restored = snapshot && restoreWorkflow(snapshot) // an identical live tree\n * await store.delete(definition.id) // drop it\n * ```\n */\nexport class MemoryWorkflowStore implements WorkflowStoreInterface {\n\treadonly #snapshots = new Map<string, WorkflowSnapshot>()\n\n\tget(id: string): Promise<WorkflowSnapshot | undefined> {\n\t\treturn Promise.resolve(this.#snapshots.get(id))\n\t}\n\n\tset(snapshot: WorkflowSnapshot): Promise<void> {\n\t\t// Insert / replace under the snapshot's OWN id (no separate id param).\n\t\tthis.#snapshots.set(snapshot.id, snapshot)\n\t\treturn Promise.resolve()\n\t}\n\n\tdelete(id: string): Promise<void> {\n\t\t// Drop by id; `Map.delete` of an absent id is already a no-op (no throw).\n\t\tthis.#snapshots.delete(id)\n\t\treturn Promise.resolve()\n\t}\n}\n","import type { EmitterInterface } from '@orkestrel/emitter'\nimport type {\n\tPhaseInterface,\n\tTaskContext,\n\tTaskEventMap,\n\tTaskInterface,\n\tTaskOptions,\n\tTaskResult,\n\tTaskSnapshot,\n\tTaskStatus,\n\tWorkflowInterface,\n} from '../types.js'\nimport { Emitter } from '@orkestrel/emitter'\nimport { WorkflowError } from '../errors.js'\nimport { canTransitionTask } from '../helpers.js'\n\n/**\n * The live leaf state machine (W-b) for one task — an observable (AGENTS §13), guarded\n * synchronous task whose explicit {@link TaskStatus} advances through the AGENTS §10\n * transitions, recording a {@link TaskResult} on a terminal outcome.\n *\n * @remarks\n * - **Guarded transitions (AGENTS §10).** `start` (→ `running`), then `complete(value)`\n * (→ `completed`, records a {@link import('@orkestrel/contract').Success}), `fail(error)`\n * (→ `failed`, records a {@link import('@orkestrel/contract').Failure}), `skip` (→ `skipped`),\n * `stop` (→ `stopped`). Each consults {@link canTransitionTask} FIRST and throws a\n * `TRANSITION` {@link WorkflowError} on an illegal move (e.g. completing a non-`running`\n * task) — the legal graph is the single source of truth, so the leaf can never reach an\n * impossible state.\n * - **Override (snapshot fidelity).** `skip` / `stop` set `#override` to the forced terminal\n * status, so a RESTORE can tell a forced leaf (`skipped` / `stopped`) from a run-produced\n * one and reinstate it AS an override — preserving the round-trip.\n * - **The cascade.** Every status change records its boxed result (when any), fires the leaf's\n * OWN event, THEN calls the parent phase's `#recompute` (injected at construction) so the\n * transition propagates UP (Task → Phase → Workflow re-derive). The own-event-before-cascade\n * order means an observer sees the CAUSE (this leaf changed) before the EFFECT (the parents\n * re-derive) — the project precedent (`Runner.#settle` emits its own `fail` before propagating).\n * - **Observable (AGENTS §13).** The owned {@link emitter} ({@link TaskEventMap}) fires the\n * matching event strictly AFTER the state change, BEFORE the cascade; the emitter isolates\n * a listener throw and routes it to its `error` handler (the `error` option), so a buggy\n * observer can never corrupt a transition.\n */\nexport class Task implements TaskInterface {\n\treadonly #context: TaskContext\n\treadonly #phase: PhaseInterface\n\treadonly #workflow: WorkflowInterface\n\t// Propagate a status change UP to the parent phase (which re-derives, then escalates to the\n\t// workflow) — injected by the parent so the leaf needs no back-reference plumbing of its own.\n\treadonly #recompute: () => void\n\treadonly #metadata: Readonly<Record<string, unknown>>\n\t// The PUSH observation surface (§13) — owned, never inherited. The emitter isolates a\n\t// listener throw (routing it to the `error` handler), so it can never escape into a\n\t// transition or the cascade.\n\treadonly #emitter: Emitter<TaskEventMap>\n\t#status: TaskStatus\n\t// The recorded outcome once the task settled with one (`completed` / `failed`), else undefined.\n\t#result: TaskResult | undefined\n\n\tconstructor(\n\t\tcontext: TaskContext,\n\t\tphase: PhaseInterface,\n\t\tworkflow: WorkflowInterface,\n\t\trecompute: () => void,\n\t\toptions?: TaskOptions,\n\t\tstatus: TaskStatus = 'pending',\n\t\tresult?: TaskResult,\n\t) {\n\t\tthis.#context = context\n\t\tthis.#phase = phase\n\t\tthis.#workflow = workflow\n\t\tthis.#recompute = recompute\n\t\tthis.#metadata = options?.metadata ?? {}\n\t\tthis.#emitter = new Emitter<TaskEventMap>({ on: options?.on, error: options?.error })\n\t\tthis.#status = status\n\t\t// A RESTORE seeds the recorded outcome (present for a `completed` / `failed` leaf), so\n\t\t// the result tree round-trips; a fresh leaf starts with none. A leaf's terminal status\n\t\t// (`skipped` / `stopped`) already encodes a forced state, so the leaf needs no separate\n\t\t// override field — the override round-trip lives on the DERIVED Phase / Workflow nodes.\n\t\tthis.#result = result\n\t}\n\n\tget emitter(): EmitterInterface<TaskEventMap> {\n\t\treturn this.#emitter\n\t}\n\n\tget id(): string {\n\t\treturn this.#context.id\n\t}\n\n\tget name(): string {\n\t\treturn this.#context.name\n\t}\n\n\tget description(): string | undefined {\n\t\treturn this.#context.description\n\t}\n\n\tget context(): TaskContext {\n\t\treturn this.#context\n\t}\n\n\tget phase(): PhaseInterface {\n\t\treturn this.#phase\n\t}\n\n\tget workflow(): WorkflowInterface {\n\t\treturn this.#workflow\n\t}\n\n\tget status(): TaskStatus {\n\t\treturn this.#status\n\t}\n\n\tget result(): TaskResult | undefined {\n\t\treturn this.#result\n\t}\n\n\tstart(): void {\n\t\tthis.#transition('running')\n\t\t// Own event FIRST, THEN the cascade — an observer sees the cause (this task started) before\n\t\t// the effect (the phase / workflow re-derive), mirroring `Runner.#settle` (AGENTS §13).\n\t\tthis.#emitter.emit('start', this.id)\n\t\tthis.#escalate()\n\t}\n\n\tcomplete(value: unknown): void {\n\t\tthis.#transition('completed')\n\t\t// Box the produced value as a Success (an inline `Result` branch, the codebase idiom) and\n\t\t// RECORD it BEFORE escalating, so the parents' `results()` already see it when the cascade\n\t\t// re-derives. Then observe the leaf's own `complete` FIRST, and escalate the cascade LAST —\n\t\t// so the leaf's own event fires before any parent's cascade event (cause before effect).\n\t\tconst result = this.#record('completed', { success: true, value })\n\t\tthis.#emitter.emit('complete', result)\n\t\tthis.#escalate()\n\t}\n\n\tfail(error: unknown): void {\n\t\tthis.#transition('failed')\n\t\t// Box the reason as a Failure — normalise a non-`Error` to an `Error` (preserving the\n\t\t// original as `cause`), matching the Queue's `#attempt` and the `TaskResult.result`\n\t\t// `Result<unknown>` (= `Result<unknown, Error>`) shape. Record BEFORE escalating (so a\n\t\t// parent's `results()` / `#failure()` sees it), observe the leaf's own `fail` FIRST, then\n\t\t// escalate the cascade LAST (a failed leaf may flip the phase / workflow to `failed` under\n\t\t// `bail` — the listener still sees cause before effect).\n\t\tconst reason = error instanceof Error ? error : new Error(String(error), { cause: error })\n\t\tconst result = this.#record('failed', { success: false, error: reason })\n\t\tthis.#emitter.emit('fail', result)\n\t\tthis.#escalate()\n\t}\n\n\tskip(): void {\n\t\t// `skip` (AGENTS §10) moves a `pending` / `running` task to the terminal `skipped` state —\n\t\t// the status itself records the forced terminal (no boxed outcome: a skip produced none).\n\t\t// Own event FIRST, THEN the cascade (cause before effect).\n\t\tthis.#transition('skipped')\n\t\tthis.#emitter.emit('skip')\n\t\tthis.#escalate()\n\t}\n\n\tstop(): void {\n\t\t// `stop` (AGENTS §10) moves a `pending` / `running` task to the terminal `stopped` state —\n\t\t// same discipline as `skip`; a stop likewise produced no boxed outcome. Own event FIRST,\n\t\t// THEN the cascade.\n\t\tthis.#transition('stopped')\n\t\tthis.#emitter.emit('stop')\n\t\tthis.#escalate()\n\t}\n\n\tsnapshot(): TaskSnapshot {\n\t\t// Pure JSON: identity + status + the recorded result + the open metadata bag. The leaf's\n\t\t// status IS its forced-terminal marker (`skipped` / `stopped`), so restore reinstates the\n\t\t// leaf from `status` directly — no separate override field is needed at the leaf.\n\t\treturn {\n\t\t\tid: this.id,\n\t\t\tname: this.name,\n\t\t\t...(this.description === undefined ? {} : { description: this.description }),\n\t\t\tstatus: this.#status,\n\t\t\t...(this.#result === undefined ? {} : { result: this.#result }),\n\t\t\tmetadata: this.#metadata,\n\t\t}\n\t}\n\n\t// Guard then apply one status move: reject an illegal transition with a `TRANSITION` error\n\t// (naming the offending current status + requested target), else set the new status. The\n\t// cascade is NOT run here — every caller records its boxed result (when any) FIRST, notifies\n\t// its OWN event SECOND, then escalates LAST, so an observer sees cause (this leaf changed)\n\t// before effect (the parents re-derive). See `start` / `complete` / `fail` / `skip` / `stop`.\n\t#transition(to: TaskStatus): void {\n\t\tif (!canTransitionTask(this.#status, to)) {\n\t\t\tthrow new WorkflowError(\n\t\t\t\t'TRANSITION',\n\t\t\t\t`task '${this.id}' cannot transition from '${this.#status}' to '${to}'`,\n\t\t\t\t{ task: this.id, from: this.#status, to },\n\t\t\t)\n\t\t}\n\t\tthis.#status = to\n\t}\n\n\t// Build the lineage-stamped {@link TaskResult} for a terminal outcome, store it as `#result`,\n\t// and return it. The boxed `result` is present only for `completed` / `failed`.\n\t#record(status: TaskStatus, result: TaskResult['result']): TaskResult {\n\t\tconst record: TaskResult = {\n\t\t\ttask: this.#context,\n\t\t\tphase: this.#context.phase,\n\t\t\tworkflow: this.#context.phase.workflow,\n\t\t\tstatus,\n\t\t\t...(result === undefined ? {} : { result }),\n\t\t\ttimestamp: Date.now(),\n\t\t}\n\t\tthis.#result = record\n\t\treturn record\n\t}\n\n\t// Notify the parent phase that this leaf changed, so it re-derives and escalates to the\n\t// workflow — the single upward step of the cascade.\n\t#escalate(): void {\n\t\tthis.#recompute()\n\t}\n}\n","import type { TaskInterface, TaskManagerInterface } from '../types.js'\n\n/**\n * The lean child manager (AGENTS §9) of a {@link import('../phases/Phase.js').Phase}'s live\n * tasks — an insertion-ordered registry keyed by task `id`, so positional order is\n * preserved across an interior `skip` / `remove`.\n *\n * @remarks\n * - **Positional store.** Tasks live in an insertion-ordered `Map` keyed by `id`;\n * `append` adds one at the end (the build-time wiring path), `task(id)` looks one up,\n * `tasks()` lists them in positional order, `count` is the size. A `skip` is a STATUS\n * change on a stored task (never a removal), so order survives it; a snapshot RESTORE\n * re-`append`s in the snapshot's order, reproducing it exactly.\n * - **No batch matrix.** A phase's tasks are a fixed positional set, so AGENTS §9.2 (the\n * bulk verb overloads) is deliberately omitted — there is no `remove` family here.\n * - **Event-free.** A purely structural container — the live {@link TaskInterface}s own\n * their own emitters; the manager observes nothing.\n *\n * @example\n * ```ts\n * const tasks = new TaskManager()\n * tasks.append(task) // a live Task\n * tasks.task(task.id) // the same task\n * tasks.count // 1\n * ```\n */\nexport class TaskManager implements TaskManagerInterface {\n\treadonly #tasks = new Map<string, TaskInterface>()\n\n\tget count(): number {\n\t\treturn this.#tasks.size\n\t}\n\n\tappend(task: TaskInterface): void {\n\t\tthis.#tasks.set(task.id, task)\n\t}\n\n\ttask(id: string): TaskInterface | undefined {\n\t\treturn this.#tasks.get(id)\n\t}\n\n\ttasks(): readonly TaskInterface[] {\n\t\treturn [...this.#tasks.values()]\n\t}\n}\n","import type { EmitterInterface } from '@orkestrel/emitter'\nimport type {\n\tPhaseContext,\n\tPhaseEventMap,\n\tPhaseInterface,\n\tPhaseOptions,\n\tPhaseSnapshot,\n\tPhaseStatus,\n\tTaskInterface,\n\tTaskManagerInterface,\n\tTaskResult,\n\tTaskSnapshot,\n\tWorkflowInterface,\n} from '../types.js'\nimport { Emitter } from '@orkestrel/emitter'\nimport { buildTaskContext, derivePhaseStatus } from '../helpers.js'\nimport { Task } from '../tasks/Task.js'\nimport { TaskManager } from '../tasks/TaskManager.js'\n\n/**\n * The live DERIVED state machine (W-b) for one phase — an observable (AGENTS §13) whose\n * {@link PhaseStatus} is computed from its tasks (never set directly) and recomputed\n * reactively as a task transitions (the middle tier of the cascade).\n *\n * @remarks\n * - **Derived status.** `status` is `#override` when one is in force, else\n * {@link derivePhaseStatus} over the live tasks' statuses. {@link #recompute} (passed to\n * each child {@link Task}) re-derives on every child transition; a CHANGE emits the matching\n * event AND escalates to the workflow ({@link #escalate}, the upward step of the cascade).\n * - **Override (AGENTS §10).** `skip` / `stop` FORCE the phase's status (e.g. skipping a whole\n * phase), overriding the derived value; the override is PERSISTED in the snapshot's own\n * `override` field and restored DIRECTLY (no divergence guess), so a forced phase round-trips.\n * - **Children (AGENTS §9).** `tasks` is the lean {@link TaskManager} (an accessor + `count`,\n * no batch matrix); built positionally from the snapshot so order survives an interior `skip`.\n * `results()` collects the settled tasks' {@link TaskResult}s (the phase tier of the result\n * tree); `workflow` navigates UP to the live parent.\n * - **Observable (AGENTS §13).** The owned {@link emitter} ({@link PhaseEventMap}) fires\n * `start` / `complete` / `fail` / `stop` on a derived-status CHANGE, strictly AFTER the\n * recompute + escalate; the emitter isolates a listener throw and routes it to its `error`\n * handler (the `error` option); `fail` carries the failing task's {@link TaskResult}.\n */\nexport class Phase implements PhaseInterface {\n\treadonly #context: PhaseContext\n\treadonly #workflow: WorkflowInterface\n\t// Escalate a derived-status change UP to the parent workflow (which re-derives under `bail`)\n\t// — injected by the parent so the phase needs no back-reference plumbing of its own.\n\treadonly #escalateUp: () => void\n\treadonly #tasks: TaskManager = new TaskManager()\n\t// The EFFECTIVE failure policy this phase runs under (`phase.bail ?? workflow.bail`, resolved\n\t// at seed time and carried on the snapshot) — read by the runner to decide fail-fast vs\n\t// settle-all for THIS phase, and by the workflow's per-phase-bail-aware status derivation.\n\treadonly #bail: boolean\n\t// The PUSH observation surface (§13) — owned, never inherited. The emitter isolates a\n\t// listener throw (routing it to the `error` handler), never the cascade.\n\treadonly #emitter: Emitter<PhaseEventMap>\n\t// The last computed status — the baseline a recompute diffs against to detect a CHANGE.\n\t#status: PhaseStatus\n\t// The forced status of a `skip` / `stop`, overriding the derived value; `undefined` ⇒ derived.\n\t#override: PhaseStatus | undefined\n\n\tconstructor(\n\t\tsnapshot: PhaseSnapshot,\n\t\tworkflow: WorkflowInterface,\n\t\tescalate: () => void,\n\t\toptions?: PhaseOptions,\n\t\tbail?: boolean,\n\t) {\n\t\tthis.#context = { id: snapshot.id, name: snapshot.name, workflow: workflow.context }\n\t\tif (snapshot.description !== undefined) {\n\t\t\tthis.#context = { ...this.#context, description: snapshot.description }\n\t\t}\n\t\tthis.#workflow = workflow\n\t\tthis.#escalateUp = escalate\n\t\t// The effective per-phase policy: the explicit workflow `bail` OVERRIDE when supplied (a\n\t\t// deliberate \"re-run the whole tree under THIS uniform policy\" knob — `createWorkflow` /\n\t\t// `restoreWorkflow` thread `options.bail` here), else the snapshot's persisted per-phase `bail`\n\t\t// (so an option-less restore is IDENTICAL — each phase's own persisted policy governs). The\n\t\t// snapshot already resolved `phase.bail ?? workflowBail` at seed time, mirroring how Workflow\n\t\t// reads its own `#bail`.\n\t\tthis.#bail = bail ?? snapshot.bail\n\t\tthis.#emitter = new Emitter<PhaseEventMap>({ on: options?.on, error: options?.error })\n\t\t// Build the live tasks positionally from the snapshot — each wired to recompute THIS phase\n\t\t// on a transition, and carrying its own restore state (status + result + metadata).\n\t\tfor (const task of snapshot.tasks) this.#append(task, options)\n\t\t// Restore the override DIRECTLY from the snapshot's own field (present only when a whole-\n\t\t// phase skip / stop forced it) — no fragile status-divergence guess. Then seed the baseline\n\t\t// from the EFFECTIVE status so a recompute diffs against the right value.\n\t\tthis.#override = snapshot.override\n\t\tthis.#status = this.status\n\t}\n\n\tget emitter(): EmitterInterface<PhaseEventMap> {\n\t\treturn this.#emitter\n\t}\n\n\tget id(): string {\n\t\treturn this.#context.id\n\t}\n\n\tget name(): string {\n\t\treturn this.#context.name\n\t}\n\n\tget description(): string | undefined {\n\t\treturn this.#context.description\n\t}\n\n\tget context(): PhaseContext {\n\t\treturn this.#context\n\t}\n\n\tget workflow(): WorkflowInterface {\n\t\treturn this.#workflow\n\t}\n\n\tget bail(): boolean {\n\t\treturn this.#bail\n\t}\n\n\tget status(): PhaseStatus {\n\t\t// The override wins when forced; otherwise the status is derived from the live tasks.\n\t\treturn this.#override ?? derivePhaseStatus(this.#statuses())\n\t}\n\n\tget tasks(): TaskManagerInterface {\n\t\treturn this.#tasks\n\t}\n\n\ttask(id: string): TaskInterface | undefined {\n\t\treturn this.#tasks.task(id)\n\t}\n\n\tresults(): readonly TaskResult[] {\n\t\t// The phase tier of the result tree — every settled task's recorded result, in positional\n\t\t// order. A `pending` / `running` task (or a forced skip / stop) contributed none.\n\t\tconst results: TaskResult[] = []\n\t\tfor (const task of this.#tasks.tasks()) {\n\t\t\tif (task.result !== undefined) results.push(task.result)\n\t\t}\n\t\treturn results\n\t}\n\n\tskip(): void {\n\t\t// `skip` (AGENTS §10) FORCES the phase to `skipped`, overriding the derived value — then\n\t\t// recompute so the change is detected + escalated (no PhaseEventMap event for a skip).\n\t\tthis.#force('skipped')\n\t}\n\n\tstop(): void {\n\t\t// `stop` (AGENTS §10) FORCES the phase to `stopped` — same override discipline as `skip`;\n\t\t// `stopped` IS a PhaseEventMap event, so this emit fires.\n\t\tthis.#force('stopped')\n\t}\n\n\tsnapshot(): PhaseSnapshot {\n\t\t// Pure JSON: identity + the EFFECTIVE status (override-or-derived) + the ACTUAL override\n\t\t// (emitted only when one is in force) + the effective `bail` this phase ran under (always —\n\t\t// a REQUIRED field, like Workflow's) + the tasks' snapshots in positional order. Persisting\n\t\t// the override + bail directly lets a restore reinstate them without guessing from a divergence.\n\t\treturn {\n\t\t\tid: this.id,\n\t\t\tname: this.name,\n\t\t\t...(this.description === undefined ? {} : { description: this.description }),\n\t\t\tstatus: this.status,\n\t\t\t...(this.#override === undefined ? {} : { override: this.#override }),\n\t\t\tbail: this.#bail,\n\t\t\ttasks: this.#tasks.tasks().map((task) => task.snapshot()),\n\t\t}\n\t}\n\n\t// Recompute the derived status after a child transition (the callback wired into each Task):\n\t// diff the new effective status against the baseline; on a CHANGE, advance the baseline, emit\n\t// the matching event, and escalate to the workflow. An override pins the status, so a forced\n\t// phase ignores further child churn. Placed so the parents settle before observers see it.\n\t#recompute(): void {\n\t\tconst next = this.status\n\t\tif (next === this.#status) {\n\t\t\t// No phase-level change, but a child still transitioned — escalate so the workflow can\n\t\t\t// re-derive (its own diff decides whether the workflow itself changed + emits).\n\t\t\tthis.#escalateUp()\n\t\t\treturn\n\t\t}\n\t\tthis.#status = next\n\t\tthis.#emitFor(next)\n\t\tthis.#escalateUp()\n\t}\n\n\t// Apply a forced status (skip / stop): set the override, then recompute so the change is\n\t// detected, emitted (when the status maps to an event), and escalated.\n\t#force(status: PhaseStatus): void {\n\t\tthis.#override = status\n\t\tthis.#recompute()\n\t}\n\n\t// Emit the PhaseEventMap event matching a newly-entered status. `running` ⇒ `start`,\n\t// `completed` ⇒ `complete`, `failed` ⇒ `fail` (with the failing task's result), `stopped`\n\t// ⇒ `stop`. `pending` / `skipped` have no event (a phase never re-enters `pending`, and a\n\t// skip is a task-tier concept) — they emit nothing.\n\t#emitFor(status: PhaseStatus): void {\n\t\tif (status === 'running') this.#emitter.emit('start', this.id)\n\t\telse if (status === 'completed') this.#emitter.emit('complete')\n\t\telse if (status === 'failed') this.#emitter.emit('fail', this.#failure())\n\t\telse if (status === 'stopped') this.#emitter.emit('stop')\n\t}\n\n\t// The failing task's REAL recorded {@link TaskResult} — the first task whose result is a\n\t// Failure — so the `fail` event carries the true cause. A phase derives `failed` ONLY when a\n\t// child failed with a `Failure` result, so one always exists when `#emitFor('failed')` calls\n\t// this: assert that invariant (§12 programmer-error guard, mirroring `Runner.#dispatch`) rather\n\t// than fabricating a synthetic result — a fake, lineage-degenerate `TaskResult` would mask the\n\t// true cause while still type-checking.\n\t#failure(): TaskResult {\n\t\tfor (const task of this.#tasks.tasks()) {\n\t\t\tconst result = task.result\n\t\t\tif (result?.result?.success === false) return result\n\t\t}\n\t\tthrow new Error(`phase '${this.id}' derived failed with no failing task result`)\n\t}\n\n\t// Build one live task from its snapshot, threading its per-task options (its own `on` /\n\t// `metadata`, keyed by id under the phase options) and its restore state, then append it.\n\t#append(task: TaskSnapshot, options: PhaseOptions | undefined): void {\n\t\tconst context = buildTaskContext(this.#context, task)\n\t\tconst created = new Task(\n\t\t\tcontext,\n\t\t\tthis,\n\t\t\tthis.#workflow,\n\t\t\t() => this.#recompute(),\n\t\t\toptions?.tasks?.[task.id],\n\t\t\ttask.status,\n\t\t\ttask.result,\n\t\t)\n\t\tthis.#tasks.append(created)\n\t}\n\n\t// The live tasks' statuses, in positional order — the input to `derivePhaseStatus`.\n\t#statuses(): readonly PhaseStatus[] {\n\t\treturn this.#tasks.tasks().map((task) => task.status)\n\t}\n}\n","import type { PhaseInterface, PhaseManagerInterface } from '../types.js'\n\n/**\n * The lean child manager (AGENTS §9) of a {@link import('../Workflow.js').Workflow}'s\n * live phases — an insertion-ordered registry keyed by phase `id`, the phase analogue\n * of {@link import('../tasks/TaskManager.js').TaskManager}.\n *\n * @remarks\n * - **Positional store.** Phases live in an insertion-ordered `Map` keyed by `id`;\n * `append` adds one at the end, `phase(id)` looks one up, `phases()` lists them in\n * positional order, `count` is the size. A snapshot RESTORE re-`append`s in the\n * snapshot's order, reproducing it exactly.\n * - **No batch matrix.** A workflow's phases are a fixed positional set, so AGENTS §9.2\n * is deliberately omitted.\n * - **Event-free.** A purely structural container — the live {@link PhaseInterface}s own\n * their own emitters.\n *\n * @example\n * ```ts\n * const phases = new PhaseManager()\n * phases.append(phase) // a live Phase\n * phases.phase(phase.id) // the same phase\n * phases.count // 1\n * ```\n */\nexport class PhaseManager implements PhaseManagerInterface {\n\treadonly #phases = new Map<string, PhaseInterface>()\n\n\tget count(): number {\n\t\treturn this.#phases.size\n\t}\n\n\tappend(phase: PhaseInterface): void {\n\t\tthis.#phases.set(phase.id, phase)\n\t}\n\n\tphase(id: string): PhaseInterface | undefined {\n\t\treturn this.#phases.get(id)\n\t}\n\n\tphases(): readonly PhaseInterface[] {\n\t\treturn [...this.#phases.values()]\n\t}\n}\n","import type { EmitterInterface } from '@orkestrel/emitter'\nimport type {\n\tPhaseDerivation,\n\tPhaseInterface,\n\tPhaseManagerInterface,\n\tPhaseSnapshot,\n\tTaskResult,\n\tWorkflowContext,\n\tWorkflowEventMap,\n\tWorkflowInterface,\n\tWorkflowOptions,\n\tWorkflowSnapshot,\n\tWorkflowStatus,\n} from './types.js'\nimport { Emitter } from '@orkestrel/emitter'\nimport { buildWorkflowContext, collectResults, deriveWorkflowStatus } from './helpers.js'\nimport { Phase } from './phases/Phase.js'\nimport { PhaseManager } from './phases/PhaseManager.js'\n\n/**\n * The live DERIVED state machine (W-b) for a whole workflow — the observable (AGENTS §13)\n * ROOT whose {@link WorkflowStatus} is computed from its phases under the `bail` policy and\n * recomputed reactively as the cascade propagates up from a task transition.\n *\n * @remarks\n * - **Construction.** Built from a {@link WorkflowSnapshot} (the unified input —\n * {@link import('./factories.js').createWorkflow} seeds an initial snapshot from a\n * {@link import('./types.js').WorkflowDefinition}, {@link import('./factories.js').restoreWorkflow}\n * passes a persisted one). Each child {@link Phase} is wired to escalate to {@link #recompute}.\n * - **Derived status.** `status` is `#override` when forced, else\n * {@link deriveWorkflowStatus} over the live phases' statuses feeding `bail`. `failed` is\n * reachable ONLY under `bail: true` (a single failed task halts the workflow); under\n * `bail: false` a failed phase folds into `completed`. {@link #recompute} diffs on each phase\n * change; a CHANGE emits.\n * - **Override (AGENTS §10).** `skip` / `stop` FORCE the status; the override is PERSISTED in the\n * snapshot's own `override` field and restored DIRECTLY (no divergence guess). The snapshot also\n * persists `bail`, so a restore re-derives status identically without a silent policy default.\n * - **Result tree.** `results()` flattens every phase's `results()` ({@link collectResults}) — the\n * workflow tier; `phase(id)` + each `phase.task(id)` navigate DOWN, a task's `phase` / `workflow`\n * navigate UP.\n * - **Snapshot.** `snapshot()` serializes the whole live tree to a {@link WorkflowSnapshot} (pure\n * JSON); {@link import('./factories.js').restoreWorkflow} rebuilds an equivalent live tree.\n * - **Observable (AGENTS §13).** The owned {@link emitter} ({@link WorkflowEventMap}) fires\n * `start` / `complete` / `fail` / `stop` on a derived-status CHANGE; the emitter isolates a\n * listener throw and routes it to its `error` handler (the `error` option); `fail` carries\n * the failing task's {@link TaskResult}.\n */\nexport class Workflow implements WorkflowInterface {\n\treadonly #context: WorkflowContext\n\treadonly #bail: boolean\n\t// The EXPLICIT workflow `bail` override (`options.bail`), when one was supplied — a deliberate\n\t// \"re-run the whole tree under THIS uniform policy\" knob threaded down to each phase so it\n\t// overrides the phase's persisted per-phase bail. `undefined` ⇒ no override (each phase keeps its\n\t// own persisted policy, so an option-less restore is identical). Distinct from `#bail` (the\n\t// resolved default), which is ALWAYS defined.\n\treadonly #bailOverride: boolean | undefined\n\treadonly #phases: PhaseManager = new PhaseManager()\n\t// The PUSH observation surface (§13) — owned, never inherited. The emitter isolates a\n\t// listener throw (routing it to the `error` handler), never the cascade.\n\treadonly #emitter: Emitter<WorkflowEventMap>\n\t// Creation / update stamps carried verbatim through a snapshot round-trip.\n\treadonly #created: number\n\t#updated: number\n\t// The last computed status — the baseline a recompute diffs against to detect a CHANGE.\n\t#status: WorkflowStatus\n\t// The forced status of a `skip` / `stop`, overriding the derived value; `undefined` ⇒ derived.\n\t#override: WorkflowStatus | undefined\n\n\tconstructor(snapshot: WorkflowSnapshot, options?: WorkflowOptions) {\n\t\tthis.#context = buildWorkflowContext(snapshot)\n\t\t// The snapshot carries the policy it ran under (the self-contained durable payload), so the\n\t\t// snapshot's `bail` is the source of truth; an explicit `options.bail` still wins when given.\n\t\tthis.#bail = options?.bail ?? snapshot.bail\n\t\t// The explicit override (only when supplied) — cascaded to every phase so it overrides their\n\t\t// persisted per-phase bail; omitted ⇒ each phase keeps its own persisted policy (identical restore).\n\t\tthis.#bailOverride = options?.bail\n\t\tthis.#emitter = new Emitter<WorkflowEventMap>({ on: options?.on, error: options?.error })\n\t\tthis.#created = snapshot.created\n\t\tthis.#updated = snapshot.updated\n\t\t// Build the live phases positionally from the snapshot — each wired to recompute THIS\n\t\t// workflow on a derived-status change, carrying its own per-phase options + restore state.\n\t\tfor (const phase of snapshot.phases) this.#append(phase, options)\n\t\t// Restore the override DIRECTLY from the snapshot's own field (present only when a whole-\n\t\t// workflow skip / stop forced it) — no fragile status-divergence guess. Then seed the\n\t\t// baseline from the EFFECTIVE status so a recompute diffs against the right value.\n\t\tthis.#override = snapshot.override\n\t\tthis.#status = this.status\n\t}\n\n\tget emitter(): EmitterInterface<WorkflowEventMap> {\n\t\treturn this.#emitter\n\t}\n\n\tget id(): string {\n\t\treturn this.#context.id\n\t}\n\n\tget name(): string {\n\t\treturn this.#context.name\n\t}\n\n\tget description(): string | undefined {\n\t\treturn this.#context.description\n\t}\n\n\tget context(): WorkflowContext {\n\t\treturn this.#context\n\t}\n\n\tget bail(): boolean {\n\t\treturn this.#bail\n\t}\n\n\tget status(): WorkflowStatus {\n\t\t// The override wins when forced; otherwise the status is derived from the live phases'\n\t\t// derivations — each phase's status paired with the EFFECTIVE `bail` it ran under, so the\n\t\t// failure outcome is per-phase-bail-aware (a strict phase halts even under a graceful workflow).\n\t\treturn this.#override ?? deriveWorkflowStatus(this.#statuses())\n\t}\n\n\tget phases(): PhaseManagerInterface {\n\t\treturn this.#phases\n\t}\n\n\tphase(id: string): PhaseInterface | undefined {\n\t\treturn this.#phases.phase(id)\n\t}\n\n\tresults(): readonly TaskResult[] {\n\t\t// The workflow tier of the result tree — every settled task's result across all phases, in\n\t\t// positional order (phases in order, each phase's task results in order).\n\t\treturn collectResults(this.#phases.phases().map((phase) => phase.results()))\n\t}\n\n\tskip(): void {\n\t\t// `skip` (AGENTS §10) FORCES the workflow to `skipped`, overriding the derived value — then\n\t\t// recompute so the change is detected (no WorkflowEventMap event for a skip).\n\t\tthis.#force('skipped')\n\t}\n\n\tstop(): void {\n\t\t// `stop` (AGENTS §10) FORCES the workflow to `stopped` — `stopped` IS a WorkflowEventMap\n\t\t// event, so this emit fires.\n\t\tthis.#force('stopped')\n\t}\n\n\tcomplete(): void {\n\t\t// Forces the workflow to `completed` (overriding the derived value), reusing the same #force\n\t\t// override machinery as skip/stop. `completed` IS a WorkflowEventMap event, so the emit fires.\n\t\t// Used by the runner to settle an EXECUTED no-op tree (no work happened ⇒ vacuously done).\n\t\tthis.#force('completed')\n\t}\n\n\tsnapshot(): WorkflowSnapshot {\n\t\t// Pure JSON: identity + the EFFECTIVE status + the ACTUAL override (emitted only when one is\n\t\t// in force) + the `bail` policy this tree ran under + the phases' snapshots in positional\n\t\t// order + the creation / update stamps. Persisting `override` and `bail` makes the payload\n\t\t// self-contained, so a restore reinstates the override directly and re-derives identically.\n\t\treturn {\n\t\t\tid: this.id,\n\t\t\tname: this.name,\n\t\t\t...(this.description === undefined ? {} : { description: this.description }),\n\t\t\tstatus: this.status,\n\t\t\t...(this.#override === undefined ? {} : { override: this.#override }),\n\t\t\tbail: this.#bail,\n\t\t\tphases: this.#phases.phases().map((phase) => phase.snapshot()),\n\t\t\tcreated: this.#created,\n\t\t\tupdated: this.#updated,\n\t\t}\n\t}\n\n\t// The top of the cascade: recompute the derived status after a phase change (the callback\n\t// wired into each Phase). Diff the new effective status against the baseline; on a CHANGE,\n\t// advance the baseline + the `updated` stamp, then emit the matching event. The workflow is\n\t// the root, so there is nothing further to escalate to.\n\t#recompute(): void {\n\t\tconst next = this.status\n\t\tif (next === this.#status) return\n\t\tthis.#status = next\n\t\tthis.#updated = Date.now()\n\t\tthis.#emitFor(next)\n\t}\n\n\t// Apply a forced status (skip / stop): set the override, then recompute so the change is\n\t// detected + emitted (when the status maps to an event).\n\t#force(status: WorkflowStatus): void {\n\t\tthis.#override = status\n\t\tthis.#recompute()\n\t}\n\n\t// Emit the WorkflowEventMap event matching a newly-entered status. `running` ⇒ `start`,\n\t// `completed` ⇒ `complete`, `failed` ⇒ `fail` (with the failing task's result, reachable only\n\t// under `bail: true`), `stopped` ⇒ `stop`. `pending` / `skipped` have no event.\n\t#emitFor(status: WorkflowStatus): void {\n\t\tif (status === 'running') this.#emitter.emit('start', this.id)\n\t\telse if (status === 'completed') this.#emitter.emit('complete')\n\t\telse if (status === 'failed') this.#emitter.emit('fail', this.#failure())\n\t\telse if (status === 'stopped') this.#emitter.emit('stop')\n\t}\n\n\t// The failing task's REAL recorded {@link TaskResult} — the first failed result across every\n\t// phase — so the `fail` event carries the true cause. A workflow derives `failed` ONLY under\n\t// `bail` when some task failed with a `Failure` result, so one always exists when\n\t// `#emitFor('failed')` calls this: assert that invariant (§12 programmer-error guard, mirroring\n\t// `Runner.#dispatch`) rather than fabricating a synthetic, lineage-degenerate result that would\n\t// mask the true cause while still type-checking.\n\t#failure(): TaskResult {\n\t\tfor (const result of this.results()) {\n\t\t\tif (result.result?.success === false) return result\n\t\t}\n\t\tthrow new Error(`workflow '${this.id}' derived failed with no failing task result`)\n\t}\n\n\t// Build one live phase from its snapshot, threading its per-phase options (keyed by id under\n\t// the workflow options) + the explicit workflow bail override (when one was supplied — it\n\t// overrides the phase's persisted per-phase bail) and wiring it to recompute THIS workflow on a\n\t// derived-status change.\n\t#append(phase: PhaseSnapshot, options: WorkflowOptions | undefined): void {\n\t\tconst created = new Phase(\n\t\t\tphase,\n\t\t\tthis,\n\t\t\t() => this.#recompute(),\n\t\t\toptions?.phases?.[phase.id],\n\t\t\tthis.#bailOverride,\n\t\t)\n\t\tthis.#phases.append(created)\n\t}\n\n\t// The live phases' derivations, in positional order — each phase's status paired with its\n\t// EFFECTIVE `bail` (phase override or the workflow default) — the input to\n\t// `deriveWorkflowStatus` (per-phase-bail-aware).\n\t#statuses(): readonly PhaseDerivation[] {\n\t\treturn this.#phases.phases().map((phase) => ({ status: phase.status, bail: phase.bail }))\n\t}\n}\n","import type { AbortInterface } from '@orkestrel/abort'\nimport type { ControllerInterface } from './types.js'\n\n/**\n * The per-unit handle a runner handler receives — wraps the unit's identity,\n * input, cancellation, and the run controls (`wait` / `spawn` / `abort`).\n *\n * @remarks\n * - **Built by the Runner per unit.** The runner constructs one `Controller` per\n * unit it dispatches, handing it the unit's `id`, `input`, the unit's `Abort`\n * handle, the queue attempt's `signal`, and a `spawn` callback that launches a\n * sibling through the same queue.\n * - **Signal.** `signal` is the queue attempt's signal, which ANY-combines the\n * unit's own abort, the runner-level abort (the runner aborts every unit), and\n * the per-attempt timeout — so it fires on any of the three. `aborted` and\n * `abort(reason)` delegate to the unit's `Abort` (the cancellation source of\n * truth); since the attempt signal ANY-includes that abort, `abort()` fires\n * `signal` too.\n * - **`wait` promise-parks (never a timer).** It resolves the instant the unit's\n * `signal` fires (immediately if already aborted) via a one-shot listener — no\n * `setTimeout`, no polling, no busy-yield — so a parked unit costs no CPU.\n * - **`spawn` is fire-and-track.** It delegates to the runner's launch-a-sibling\n * callback, which routes the sibling through the queue; the runner's `execute`\n * awaits the spawn closure, so the sibling runs whether or not its promise is\n * awaited. (Inline-awaiting a spawn from a slot-holding handler on a bounded\n * runner can deadlock — fan out instead; see {@link ControllerInterface.spawn}.)\n * - **Event-free by design.** The per-unit handle carries no Emitter; observe the\n * {@link RunnerInterface.emitter} instead (`unit` / `spawn` / `settle` / `fail` carry the id).\n */\nexport class Controller<TInput, TResult> implements ControllerInterface<TInput, TResult> {\n\treadonly id: string\n\treadonly input: TInput\n\treadonly signal: AbortSignal\n\t// The unit's cancellation handle — the source of truth for `aborted` / `abort`.\n\treadonly #abort: AbortInterface\n\t// The runner's launch-a-sibling callback — routes a spawn through the queue.\n\treadonly #spawn: (input: TInput) => Promise<TResult>\n\n\tconstructor(\n\t\tid: string,\n\t\tinput: TInput,\n\t\tabort: AbortInterface,\n\t\tsignal: AbortSignal,\n\t\tspawn: (input: TInput) => Promise<TResult>,\n\t) {\n\t\tthis.id = id\n\t\tthis.input = input\n\t\tthis.#abort = abort\n\t\tthis.signal = signal\n\t\tthis.#spawn = spawn\n\t}\n\n\tget aborted(): boolean {\n\t\treturn this.#abort.aborted\n\t}\n\n\twait(): Promise<void> {\n\t\t// Promise-park on the unit's signal — resolve immediately if already aborted,\n\t\t// else on the one-shot 'abort' event. No timer, no poll (the B1 fix).\n\t\tif (this.signal.aborted) return Promise.resolve()\n\t\treturn new Promise<void>((resolve) => {\n\t\t\tthis.signal.addEventListener('abort', () => resolve(), { once: true })\n\t\t})\n\t}\n\n\tspawn(input: TInput): Promise<TResult> {\n\t\treturn this.#spawn(input)\n\t}\n\n\tabort(reason?: unknown): void {\n\t\tthis.#abort.abort(reason)\n\t}\n}\n","import type { AbortInterface } from '@orkestrel/abort'\nimport type { EmitterInterface } from '@orkestrel/emitter'\nimport type { QueueExecution, QueueInterface } from '@orkestrel/queue'\nimport type {\n\tDeferredInterface,\n\tRunnerEventMap,\n\tRunnerInterface,\n\tRunnerOptions,\n\tRunnerUnit,\n\tUnitOutcome,\n} from './types.js'\nimport { createAbort } from '@orkestrel/abort'\nimport { createQueue } from '@orkestrel/queue'\nimport { Emitter } from '@orkestrel/emitter'\nimport { createDeferred } from './helpers.js'\nimport { Controller } from './Controller.js'\n\n/**\n * A thin generic orchestrator that drives declared units — and any they `spawn` —\n * through a bounded-concurrency {@link createQueue}, collecting ordered results.\n *\n * @remarks\n * - **Drives the Queue (no reimplemented concurrency).** Every unit (declared or\n * spawned) is `enqueue`d on one internal `Queue`, so backpressure, FIFO ordering,\n * bounded concurrency, retries, and the per-attempt timeout are all the Queue's —\n * the Runner adds only orchestration (launching, ordering, draining, fail-fast).\n * - **Spawns actually run, results stay ordered (the B2 fix).** Declared inputs and\n * `spawn`ed siblings flow through the SAME `#launch`, which appends the unit's `id`\n * to an ordered `#order` list and records its settled value into `#values` by `id`.\n * Results are read back as `#order.map(id => #values.get(id))` — declared first (in\n * input order), then spawns (in spawn order). There is no one-time task snapshot,\n * so a unit spawned mid-handler is run and ordered like any other.\n * - **`execute` awaits the full spawn closure via a count gate.** `#launch` increments\n * an outstanding-unit `#count` BEFORE enqueuing and every settle decrements it,\n * resolving the `#drained` deferred at zero. Because `spawn` calls `#launch` (so\n * `#count += 1`) before the parent handler returns, the count never reaches zero\n * mid-run — `execute` parks on `#drained` and so awaits the entire transitive\n * closure, not just the declared units.\n * - **`spawn` is fire-and-track.** A spawned unit runs through the queue regardless of\n * whether its promise is awaited; the Runner never awaits a spawned promise from\n * within a handler's slot (it awaits the count gate instead), so a slot-holding\n * handler can fan out without the Runner deadlocking it. (An inline `await` of a\n * spawn by a bounded handler can still deadlock — that caveat is the caller's.)\n * - **Per-unit Controller + signal.** Each unit gets a `Controller` carrying its `id`,\n * `input`, the unit's `Abort` (so `aborted` / `abort` delegate to it), and the queue\n * attempt's `signal` (which ANY-combines the unit abort + runner abort + timeout). A\n * `spawn` callback is injected so `controller.spawn(input)` delegates to `#launch`.\n * - **One-shot + fail-fast.** `execute` runs once (a second call throws). The first\n * unit failure (after its retries) records the error and `abort()`s the run, so every\n * sibling's signal fires; later failures are ignored and `execute` rejects with the\n * first error. A user `abort(reason)` likewise rejects a running `execute`.\n * - **Observable (§13).** The owned {@link emitter} ({@link RunnerEventMap}) carries the run\n * lifecycle — `start` / `unit` / `spawn` / `settle` / `fail` / `finish` / `abort` — for\n * fire-and-forget observers. Every event is emitted directly, strictly AFTER the relevant\n * launch / settle / drain transition; the emitter isolates a listener throw and routes it\n * to its `error` handler (the `error` option), so a buggy observer can NEVER reorder, throw\n * into, or corrupt the one-shot / fail-fast / spawn-tracking engine: the outstanding-unit\n * count gate stays balanced and fail-fast still fires regardless of what a listener does.\n * Observation is purely a side-channel.\n */\nexport class Runner<TInput, TResult> implements RunnerInterface<TInput, TResult> {\n\treadonly #handler: RunnerOptions<TInput, TResult>['handler']\n\t// The per-entry reliability resolver — spread into each enqueue so a unit's `retries` /\n\t// `timeout` OVERRIDE the queue-level defaults (the Queue resolves default→override). Optional:\n\t// with none supplied, the enqueue is byte-identical to the no-resolver path.\n\treadonly #entries: RunnerOptions<TInput, TResult>['entries']\n\treadonly #queue: QueueInterface<RunnerUnit<TInput>, TResult>\n\t// The PUSH observation surface (§13) — owned, never inherited. The emitter isolates a\n\t// listener throw (routing it to the `error` handler), so it can never escape into the\n\t// count gate / fail-fast / spawn tracking.\n\treadonly #emitter: Emitter<RunnerEventMap<TResult>>\n\t// Each unit's cancellation handle, by id — aborted en masse on a runner abort.\n\treadonly #aborts = new Map<string, AbortInterface>()\n\t// The launch order of every unit (declared, then spawns) — the result ordering.\n\treadonly #order: string[] = []\n\t// Each unit's settled value, by id — boxed so presence is tracked by map membership\n\t// (not by an `undefined` sentinel), correct even when `TResult` includes `undefined`.\n\treadonly #values = new Map<string, { readonly value: TResult }>()\n\t// Outstanding (launched-but-unsettled) units; `#drained` resolves when it hits 0.\n\t#count = 0\n\t#drained: DeferredInterface<void> | undefined\n\t#started = false\n\t#running = false\n\t#stopped = false\n\t// The first unit failure (fail-fast) — `execute` rejects with it once drained.\n\t#failure: { readonly error: unknown } | undefined\n\n\tconstructor(options: RunnerOptions<TInput, TResult>) {\n\t\tthis.#handler = options.handler\n\t\tthis.#entries = options.entries\n\t\tthis.#emitter = new Emitter<RunnerEventMap<TResult>>({ on: options?.on, error: options?.error })\n\t\tthis.#queue = createQueue<RunnerUnit<TInput>, TResult>({\n\t\t\thandler: (unit, execution) => this.#dispatch(unit, execution),\n\t\t\tconcurrency: options.concurrency,\n\t\t\tretries: options.retries,\n\t\t\ttimeout: options.timeout,\n\t\t})\n\t}\n\n\tget emitter(): EmitterInterface<RunnerEventMap<TResult>> {\n\t\treturn this.#emitter\n\t}\n\n\tget active(): number {\n\t\treturn this.#count\n\t}\n\n\tget stopped(): boolean {\n\t\treturn this.#stopped\n\t}\n\n\tasync execute(inputs: readonly TInput[]): Promise<readonly TResult[]> {\n\t\tif (this.#started) throw new Error('runner has already executed')\n\t\tif (this.#stopped) throw new Error('runner is stopped')\n\t\tthis.#started = true\n\t\tthis.#running = true\n\t\t// Observe the run beginning — AFTER the one-shot / stopped guards passed and the run is\n\t\t// marked started + running, so a swallowed listener throw can't perturb the launch.\n\t\tthis.#emitter.emit('start')\n\t\t// An empty run has nothing to drain — resolve to [] without arming the gate.\n\t\tif (inputs.length === 0) {\n\t\t\tthis.#running = false\n\t\t\t// The (trivially) settled batch — observe `finish` with the empty result.\n\t\t\tthis.#emitter.emit('finish', [])\n\t\t\treturn []\n\t\t}\n\t\tconst drained = createDeferred<void>()\n\t\tthis.#drained = drained\n\t\tfor (const input of inputs) void this.#launch(input)\n\t\tawait drained.promise\n\t\tthis.#running = false\n\t\tif (this.#failure !== undefined) throw this.#failure.error\n\t\t// The batch drained successfully — observe `finish` with the ordered results, AFTER the\n\t\t// drained gate resolved and the fail-fast check passed (a failed run throws above and\n\t\t// emits no `finish`; its per-unit `fail` + run-level `abort` already fired).\n\t\tconst results = this.#collect()\n\t\tthis.#emitter.emit('finish', results)\n\t\treturn results\n\t}\n\n\tabort(reason?: unknown): void {\n\t\tif (this.#stopped) return\n\t\t// Record an abort as the run's failure (if none yet) so a parked `execute` rejects\n\t\t// rather than returning partial results. Preserve the caller's `reason` verbatim —\n\t\t// it is the same value the unit signals carry (the abort flows to each unit's\n\t\t// signal), and symmetric with `#settle`, which stores `outcome.error` as-is — only\n\t\t// synthesizing an Error when no reason was given. The `#failure === undefined` guard\n\t\t// keeps the FIRST failure (a fail-fast handler error recorded in `#settle` before its\n\t\t// own `this.abort(...)` call) from being overwritten by the abort's write.\n\t\tif (this.#running && this.#failure === undefined) {\n\t\t\tthis.#failure = { error: reason === undefined ? new Error('runner aborted') : reason }\n\t\t}\n\t\tthis.#cancel(reason)\n\t\tthis.#queue.abort(reason)\n\t\tthis.#stopped = true\n\t\t// Observe the abort — AFTER every unit's signal fired, the backing queue was aborted,\n\t\t// and the run was marked stopped, so a swallowed listener throw can't perturb the\n\t\t// cancel. Idempotent at the top (a second `abort` returns early), so this fires once.\n\t\tthis.#emitter.emit('abort', reason)\n\t}\n\n\tdestroy(): void {\n\t\tif (this.#stopped) {\n\t\t\tthis.#queue.destroy()\n\t\t\treturn\n\t\t}\n\t\tthis.abort()\n\t\tthis.#queue.destroy()\n\t}\n\n\t// Launch one unit (a declared input or a spawned sibling) through the shared queue.\n\t// Increments `#count` BEFORE enqueuing — so a spawn keeps the count above zero until\n\t// the spawned unit itself settles, making `execute` await the full closure (B2). The\n\t// settle bookkeeping records the value / first failure and drains at zero. A `parent`\n\t// (present only for a `spawn`) means this is a sub-unit — observe it as a `spawn` AFTER\n\t// the unit's id is minted, tracked, and the count incremented (so the gate already\n\t// accounts for it), BEFORE enqueuing; a declared launch (no parent) emits no `spawn`.\n\t#launch(input: TInput, parent?: string): Promise<TResult> {\n\t\tconst id = crypto.randomUUID()\n\t\tconst abort = createAbort()\n\t\tthis.#aborts.set(id, abort)\n\t\tthis.#order.push(id)\n\t\tthis.#count += 1\n\t\tif (parent !== undefined) this.#emitter.emit('spawn', id, parent)\n\t\t// Resolve the unit's per-entry reliability overrides (`retries` / `timeout`) from its input\n\t\t// and spread them into the enqueue AFTER the Runner-managed `id` / `signal` — the Queue\n\t\t// resolves default→override, so a resolved value wins over the queue-level default and an\n\t\t// absent one (or no resolver at all) falls back to it (byte-identical to the prior behavior).\n\t\tconst promise = this.#queue.enqueue(\n\t\t\t{ id, input },\n\t\t\t{ id, signal: abort.signal, ...this.#entries?.(input) },\n\t\t)\n\t\tpromise.then(\n\t\t\t(value) => this.#settle(id, { ok: true, value }),\n\t\t\t(error: unknown) => this.#settle(id, { ok: false, error }),\n\t\t)\n\t\treturn promise\n\t}\n\n\t// The queue handler for one unit: build its Controller over the attempt signal and\n\t// run the user handler against it. The unit's own `Abort` was passed as the entry\n\t// signal, so `execution.signal` already fires on unit abort, runner abort, or timeout\n\t// — expose THAT as `controller.signal` (covering all three); `abort` / `aborted`\n\t// delegate to the unit `Abort` via the Controller.\n\t#dispatch(unit: RunnerUnit<TInput>, execution: QueueExecution): Promise<TResult> | TResult {\n\t\t// `#launch` always stores the unit's `Abort` BEFORE enqueuing, so this lookup is an\n\t\t// invariant, never optional. Assert it (§12 programmer-error guard — narrows to a\n\t\t// defined `Abort` without `!`) rather than fabricating a fresh, unlinked abort: a\n\t\t// fallback `Abort` would be divorced from this entry's `execution.signal`, silently\n\t\t// severing the unit's cancellation while the type still type-checked.\n\t\tconst abort = this.#aborts.get(unit.id)\n\t\tif (abort === undefined) throw new Error('unit abort missing')\n\t\tconst controller = new Controller<TInput, TResult>(\n\t\t\tunit.id,\n\t\t\tunit.input,\n\t\t\tabort,\n\t\t\texecution.signal,\n\t\t\t(input) => this.#spawn(input, unit.id),\n\t\t)\n\t\t// Observe the unit beginning — the queue has dequeued it and is about to run its\n\t\t// handler (mirrors the Queue's own `start`); AFTER the invariant abort lookup, BEFORE\n\t\t// the user handler runs, so a swallowed listener throw can't perturb the dispatch.\n\t\tthis.#emitter.emit('unit', unit.id)\n\t\treturn this.#handler(controller)\n\t}\n\n\t// `controller.spawn(input)` — only valid DURING a run; routes the sibling through\n\t// the same `#launch` (and thus the queue), so it actually runs and is ordered. The\n\t// spawning unit's `parent` id flows through so `#launch` can observe the `spawn`.\n\t#spawn(input: TInput, parent: string): Promise<TResult> {\n\t\tif (!this.#running) throw new Error('spawn is unavailable outside an active run')\n\t\treturn this.#launch(input, parent)\n\t}\n\n\t// Record one unit's outcome, then decrement the outstanding count and drain at zero.\n\t// The FIRST failure is fail-fast: store it and `abort()` so every sibling's signal\n\t// fires; later failures (incl. the abort-induced rejections) are ignored. A success\n\t// boxes its value by id (presence by membership, so `undefined` is a valid result).\n\t#settle(id: string, outcome: UnitOutcome<TResult>): void {\n\t\tif (outcome.ok) {\n\t\t\tthis.#values.set(id, { value: outcome.value })\n\t\t\t// Observe the successful unit — AFTER its value is recorded (the unit is settled);\n\t\t\t// the emit only OBSERVES it and runs before the count decrement, so it cannot\n\t\t\t// perturb the drain that follows.\n\t\t\tthis.#emitter.emit('settle', id)\n\t\t} else if (this.#failure === undefined) {\n\t\t\tthis.#failure = { error: outcome.error }\n\t\t\t// Observe the FIRST (fail-fast) failure — AFTER the error is recorded, BEFORE the\n\t\t\t// cascade `abort()` (so observers see cause `fail` then effect `abort`). Only the\n\t\t\t// first failure emits `fail`; the abort-induced sibling rejections are ignored\n\t\t\t// (they fall through neither branch), matching fail-fast's \"later failures ignored\".\n\t\t\tthis.#emitter.emit('fail', id, outcome.error)\n\t\t\tthis.abort(outcome.error)\n\t\t}\n\t\tthis.#count -= 1\n\t\t// `#count` is incremented once per launch and decremented once per settle, so it\n\t\t// reaches exactly 0 — assert that honestly. `<= 0` would mask an over-decrement\n\t\t// regression (a double-settle) as a silent early drain; `=== 0` surfaces it instead.\n\t\tif (this.#count === 0) this.#drained?.resolve()\n\t}\n\n\t// Read every settled value back in launch order (declared first, then spawns) — by\n\t// map membership, so a `TResult` of `undefined` is preserved (not treated as absent).\n\t#collect(): readonly TResult[] {\n\t\tconst results: TResult[] = []\n\t\tfor (const id of this.#order) {\n\t\t\tconst box = this.#values.get(id)\n\t\t\tif (box !== undefined) results.push(box.value)\n\t\t}\n\t\treturn results\n\t}\n\n\t// Abort every tracked unit's cancellation handle (fires each Controller's signal).\n\t#cancel(reason: unknown): void {\n\t\tfor (const abort of this.#aborts.values()) abort.abort(reason)\n\t}\n}\n","import type { TaskContext, TaskControllerInterface, TaskResult } from '../types.js'\n\n/**\n * The lean per-task handle a {@link import('./types.js').WorkflowFunction} receives — the\n * running task's folded cancellation, its input, its lineage, and read-UP access to the\n * result tree.\n *\n * @remarks\n * - **A leaf handle, NOT the runner `Controller`.** A workflow task is a leaf of the\n * declarative W-b tree, not a fan-out unit, so this carries none of the runner\n * `Controller`'s `spawn` / `wait` — only what a leaf needs.\n * - **Folded signal.** `signal` is the cancellation the runner folds for THIS run: it fires\n * on a workflow-level abort / timeout / budget ceiling, or — under `bail: true` — when a\n * sibling task fails (the runner aborts the in-flight siblings via the substrate's\n * fail-fast). A handler races its work against it; `aborted` reads it.\n * - **Input + lineage.** `input` is the task's open `metadata` bag (its\n * {@link import('./types.js').TaskInput} payload, `{}` when none); `task` is the full\n * {@link TaskContext}, so `task.phase` / `task.phase.workflow` navigate UP the lineage.\n * - **Read-up results.** `results()` returns every settled task's {@link TaskResult} across\n * the phases that have already finished (a closure over the live\n * {@link import('./types.js').WorkflowInterface}), so a `function` task can read an earlier\n * phase's output. Read-only — a task records its OWN outcome by returning / throwing, not\n * by mutating the tree.\n * - **Event-free.** Like the runner `Controller`, the per-task handle carries no Emitter;\n * observe the W-b entities' own emitters (`task.emitter` / `phase.emitter`) instead.\n */\nexport class TaskController implements TaskControllerInterface {\n\treadonly signal: AbortSignal\n\treadonly input: Readonly<Record<string, unknown>>\n\treadonly task: TaskContext\n\t// Read the live workflow's settled results on demand — a closure injected by the runner,\n\t// so the handle reaches UP the tree without holding a back-reference to the workflow entity.\n\treadonly #results: () => readonly TaskResult[]\n\n\tconstructor(\n\t\tsignal: AbortSignal,\n\t\tinput: Readonly<Record<string, unknown>>,\n\t\ttask: TaskContext,\n\t\tresults: () => readonly TaskResult[],\n\t) {\n\t\tthis.signal = signal\n\t\tthis.input = input\n\t\tthis.task = task\n\t\tthis.#results = results\n\t}\n\n\tget aborted(): boolean {\n\t\treturn this.signal.aborted\n\t}\n\n\tresults(): readonly TaskResult[] {\n\t\treturn this.#results()\n\t}\n}\n","import type { AbortInterface } from '@orkestrel/abort'\nimport type { AgentInterface, ToolManagerInterface } from '@orkestrel/agent'\nimport type { TimeoutInterface } from '@orkestrel/timeout'\nimport type {\n\tControllerInterface,\n\tPhaseDefinition,\n\tPhaseInterface,\n\tRunnerInterface,\n\tSchedulerInterface,\n\tTaskDefinition,\n\tTaskInterface,\n\tWorkflowAgents,\n\tWorkflowDefinition,\n\tWorkflowFunctions,\n\tWorkflowInterface,\n\tWorkflowResult,\n\tWorkflowRunOptions,\n\tWorkflowRunnerInterface,\n\tWorkflowToolBinder,\n} from './types.js'\nimport { createAbort } from '@orkestrel/abort'\nimport { createTimeout } from '@orkestrel/timeout'\nimport { DEFAULT_BAIL, DEFAULT_PHASE_CONCURRENCY, MAX_WORKFLOW_DEPTH } from './constants.js'\nimport { WorkflowError } from './errors.js'\nimport {\n\tagentTag,\n\tdefinitionToSnapshot,\n\tisAgentTask,\n\tisFunctionTask,\n\tisToolTask,\n\tworkflowTag,\n} from './helpers.js'\nimport { Runner } from './Runner.js'\nimport { TaskController } from './tasks/TaskController.js'\nimport { Workflow } from './Workflow.js'\n\n// A unit of phase work is one live `TaskInterface` — the substrate Runner's `TInput`. Its\n// handler's resolved value is irrelevant (the OUTCOME is recorded on the live task via\n// `complete` / `fail` / `skip`, NOT in the Runner's ordered results), so the Runner's\n// `TResult` is `void`: the runner DRIVES the entity, the substrate only sequences + bounds.\n//\n// The run-level cancel reads the active phase Runner through a LOCAL per-`#execute` cell (an\n// inline `{ runner }` holder threaded into `#runPhase`), NOT a shared `#active` field — so a\n// NESTED `execute` (an `agent` task whose subagent authored + ran a workflow through the bound\n// workflow tool, re-entering this same runner instance while the outer run is suspended at\n// `await agent.generate()`) gets its OWN cell and can never clobber the outer run's. Each run\n// cancels exactly its own phase Runner. The injected `WorkflowToolBinder` (`createWorkflowTool`,\n// threaded at construction) lets the runner BIND a depth/cycle-aware workflow tool onto a\n// dispatched subagent WITHOUT importing its own `factories.ts` (the factories→classes direction).\n\n/**\n * The thin orchestrator that EXECUTES a live W-b workflow tree by COMPOSING the shipped\n * substrate — phases sequential, tasks concurrent — dispatching each task BY NAME under the\n * `bail` policy, including the W-c2 `agent` form behind a depth + cycle guard.\n *\n * @remarks\n * - **Composes, never re-implements.** Per-phase bounded concurrency is one\n * {@link createRunner} per phase (the substrate {@link RunnerInterface} over the workers\n * `Queue`); `bail` maps onto that Runner's fail-fast vs settle-all; the run-level abort /\n * timeout / budget fold through {@link createAbort} / {@link createTimeout} +\n * `AbortSignal.any` (exactly as the agent runtime folds its bounds); pacing is the shipped\n * {@link SchedulerInterface}. The runner writes ZERO concurrency / retry / abort logic of\n * its own — it only sequences phases, dispatches a task, and drives the live entity.\n * - **Phases sequential, tasks concurrent.** `#execute` awaits the phases in order (phase\n * N+1 starts only once phase N has fully settled). Within a phase, ALL its tasks are the\n * one Runner's `inputs`, run at `concurrency` = the phase's\n * {@link PhaseDefinition.concurrency} (default {@link DEFAULT_PHASE_CONCURRENCY}).\n * - **Dispatch by name.** `#dispatch` branches on the task's\n * {@link import('./types.js').TaskForm} (read from the `definition`, correlated by `id`):\n * `function` → the {@link WorkflowFunctions} registry, `tool` → the\n * {@link ToolManagerInterface}, `agent` → the {@link WorkflowAgents} resolver (W-c2). A\n * handler that is NOT found (an unregistered name for ANY form) AUTO-COMPLETES — the\n * ROADMAP no-handler rule.\n * - **`agent` form + depth/cycle guard (W-c2).** An `agent` task resolves its subagent via\n * `agents`, BINDS a depth/cycle-aware workflow tool onto the subagent's `context.tools`\n * (the propagation seam), folds the task's cancellation into the agent run (a workflow\n * cancel `abort`s the subagent), and drives it: success → `complete(result)`, throw →\n * `fail(error)`. Before running, the guard REJECTS the task into a typed `DEPTH`\n * {@link WorkflowError} (`fail`) when running it would push the nested chain past\n * {@link MAX_WORKFLOW_DEPTH}, OR when its target agent is already an ancestor (a cycle).\n * The rejected task never runs the agent.\n * - **`bail` → substrate.** Under `bail: true` (halt) a genuine task failure `fail`s the leaf\n * THEN re-throws, so the substrate Runner fail-fasts — it aborts the in-flight siblings\n * (their `controller.signal` fires; a mid-flight sibling `skip`s) and rejects the phase run;\n * `#execute` then `skip`s the remaining tasks / phases (the workflow derives `failed`).\n * Under `bail: false` (graceful) a failure `fail`s the leaf and RESOLVES (never throws), so\n * the Runner settles every unit (allSettled) and the run finishes (the workflow derives\n * `completed`, the failure recorded in the result tree).\n * - **Abort / Timeout / Budget fold.** `#execute` folds the run's external `signal`, a\n * {@link TimeoutInterface}, and the `@orkestrel/budget` package's `BudgetInterface`'s\n * `signal` into one `runSignal` (`AbortSignal.any`); a fire aborts the active phase's Runner\n * (cancelling every in-flight task) and HALTS the run — the remaining tasks / phases `skip`\n * and the workflow is force-`stop`ped (settles `stopped`). Each task's\n * {@link TaskController} signal `AbortSignal.any`-combines the substrate per-unit signal with\n * `runSignal`, so a handler observes either cause directly.\n * - **Re-entrant-safe.** No shared per-run mutable field: the active-Runner holder is LOCAL to\n * each `#execute`, so a nested `execute` (the bound workflow tool re-entering this instance\n * while the outer run is suspended on an `agent` task) cannot clobber the outer run's state.\n */\nexport class WorkflowRunner implements WorkflowRunnerInterface {\n\treadonly #functions: WorkflowFunctions\n\treadonly #tools: ToolManagerInterface | undefined\n\treadonly #agents: WorkflowAgents | undefined\n\treadonly #scheduler: SchedulerInterface\n\t// The injected `createWorkflowTool` (see `WorkflowToolBinder`) — `undefined` only when the\n\t// runner was constructed WITHOUT the binder (no agent can then author a nested workflow; an\n\t// agent task still runs, just with no workflow tool bound). `createWorkflowRunner` always\n\t// threads it.\n\treadonly #workflowTool: WorkflowToolBinder | undefined\n\n\tconstructor(\n\t\tfunctions: WorkflowFunctions,\n\t\ttools: ToolManagerInterface | undefined,\n\t\tagents: WorkflowAgents | undefined,\n\t\tscheduler: SchedulerInterface,\n\t\tworkflowTool: WorkflowToolBinder | undefined,\n\t) {\n\t\tthis.#functions = functions\n\t\tthis.#tools = tools\n\t\tthis.#agents = agents\n\t\tthis.#scheduler = scheduler\n\t\tthis.#workflowTool = workflowTool\n\t}\n\n\texecute(definition: WorkflowDefinition, options?: WorkflowRunOptions): Promise<WorkflowResult> {\n\t\t// SINGLE SOURCE OF TRUTH: build the live tree from the SAME definition we drive, so the\n\t\t// executed entity can never drift from the `run` form / `concurrency` metadata. The\n\t\t// WorkflowOptions half (initial `on` listeners + a `bail` override + the per-node `phases`\n\t\t// bag) is applied to the constructed `Workflow` (resolving `bail` as `options.bail ??\n\t\t// definition.bail ?? DEFAULT_BAIL`); the run-control bounds (signal/timeout/budget) feed\n\t\t// the fold in `#execute`, and the W-c2 depth/ancestry bookkeeping bounds nested recursion.\n\t\t// The tree is built DIRECTLY (not via `createWorkflow`) so the runner never imports its own\n\t\t// module's factory — preserving this codebase's factories→classes direction (no\n\t\t// class↔factory cycle).\n\t\tconst bail = options?.bail ?? definition.bail ?? DEFAULT_BAIL\n\t\t// Seed BOTH tiers of the snapshot with the effective bail (`definitionToSnapshot`'s 2nd arg) so\n\t\t// an `options.bail` override reaches each INHERITING phase's snapshot (a per-phase `bail` still\n\t\t// wins). `options` is forwarded UNCHANGED (NOT `{ ...options, bail }`): the snapshot already\n\t\t// carries the resolved bail at both tiers, so `Workflow` reads `#bail` from it; injecting a\n\t\t// resolved `bail` would make `Workflow` treat it as an EXPLICIT uniform override and clobber the\n\t\t// per-phase overrides. A caller's genuine `options.bail` stays in `options` and cascades uniformly.\n\t\tconst workflow = new Workflow(definitionToSnapshot(definition, bail), options)\n\t\t// This run's depth (default 0) and the ancestry every task inherits — the run's own\n\t\t// `workflow:<id>` added so a nested workflow that re-enters this same id is a detectable\n\t\t// cycle. A top-level caller omits both; the bound workflow tool supplies them, incremented.\n\t\tconst depth = options?.depth ?? 0\n\t\tconst ancestry = [...(options?.ancestry ?? []), workflowTag(definition.id)]\n\t\treturn this.#execute(workflow, definition, options, depth, ancestry)\n\t}\n\n\t// Drive the whole tree: arm the run-level bounds (the folded abort), run the phases\n\t// SEQUENTIALLY, then assemble the terminal result. A run-level cancel halts the loop and\n\t// force-`stop`s the workflow; otherwise the workflow's derived status is the outcome. The\n\t// active-Runner `holder` is LOCAL (re-entrant-safe — a nested execute gets its own).\n\tasync #execute(\n\t\tworkflow: WorkflowInterface,\n\t\tdefinition: WorkflowDefinition,\n\t\toptions: WorkflowRunOptions | undefined,\n\t\tdepth: number,\n\t\tancestry: readonly string[],\n\t): Promise<WorkflowResult> {\n\t\t// Arm the deadline + budget and fold every present bound into ONE run signal the tasks\n\t\t// race against — the same fold the agent runtime uses (`AbortSignal.any` of external\n\t\t// signal + deadline + budget), so a fire of any cancels every in-flight task.\n\t\t// Arm the deadline ONLY for a strictly-positive `timeout`: a non-positive value (`0` or\n\t\t// negative) means NO deadline (honouring the WorkflowRunOptions.timeout contract), so\n\t\t// `0` must NOT cancel the run on the next tick.\n\t\tconst ms = options?.timeout\n\t\tconst timeout = ms !== undefined && ms > 0 ? createTimeout({ ms }) : undefined\n\t\ttimeout?.start()\n\t\toptions?.budget?.start()\n\t\tconst runSignal = this.#fold(options, timeout)\n\t\t// On a run-level cancel, abort the ACTIVE phase's Runner (cancelling its in-flight tasks).\n\t\t// The active Runner is swapped per phase via the LOCAL holder; a closure over it always\n\t\t// fires the current one. A one-shot listener (the run halts once); cleared in the `finally`.\n\t\tconst holder: { runner: RunnerInterface<TaskInterface, void> | undefined } = {\n\t\t\trunner: undefined,\n\t\t}\n\t\tconst onCancel = (): void => holder.runner?.abort(runSignal?.reason)\n\t\tif (runSignal !== undefined) {\n\t\t\tif (runSignal.aborted) onCancel()\n\t\t\telse runSignal.addEventListener('abort', onCancel, { once: true })\n\t\t}\n\t\ttry {\n\t\t\tconst phases = workflow.phases.phases()\n\t\t\tfor (let index = 0; index < phases.length; index += 1) {\n\t\t\t\tconst phase = phases[index]\n\t\t\t\tif (phase === undefined) continue\n\t\t\t\t// A run-level cancel (or a prior bail-true failure that left the workflow non-running)\n\t\t\t\t// HALTS the loop: skip THIS and every remaining phase's tasks, then break. Read the\n\t\t\t\t// cancel state fresh (the signal may have fired during the previous phase).\n\t\t\t\tif (this.#cancelled(runSignal) || this.#halted(workflow)) {\n\t\t\t\t\tthis.#skipFrom(phases, index)\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\t// Run the phase to settlement. Under bail-true it REJECTS on the first failure\n\t\t\t\t// (fail-fast) — skip the remaining phases; otherwise it settles all and continues.\n\t\t\t\tconst failed = await this.#runPhase(\n\t\t\t\t\tworkflow,\n\t\t\t\t\tphase,\n\t\t\t\t\tthis.#phaseOf(definition, phase.id),\n\t\t\t\t\trunSignal,\n\t\t\t\t\tholder,\n\t\t\t\t\tdepth,\n\t\t\t\t\tancestry,\n\t\t\t\t)\n\t\t\t\tif (failed) {\n\t\t\t\t\tthis.#skipFrom(phases, index + 1)\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\t// Pace BETWEEN phases (never after the last) — the cooperative host yield, the\n\t\t\t\t// shipped scheduler honouring the run signal (an aborted yield rejects, handled). A\n\t\t\t\t// cancel during the phase skips pacing (the next iteration's halt guard handles it).\n\t\t\t\tif (index < phases.length - 1 && !this.#cancelled(runSignal)) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait this.#scheduler.yield(runSignal === undefined ? undefined : { signal: runSignal })\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// An aborted yield rejects with the run signal's reason — a cancel, not an error;\n\t\t\t\t\t\t// the next loop iteration's halt guard skips the rest.\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// A run-level cancel makes the run STOPPED. The substrate RACES an in-flight handler out\n\t\t\t// on abort (its result discarded), so a slow-settling task (notably an `agent` task whose\n\t\t\t// subagent takes several ticks to unwind) may still read `running` at this point — sweep\n\t\t\t// EVERY phase to `skip` any task the cancel left non-terminal, so the returned tree is\n\t\t\t// deterministic regardless of handler-settle speed (the detached handler's own later\n\t\t\t// `skip` is then a guarded no-op). THEN force the workflow `stop` so it settles `stopped`\n\t\t\t// (its derived status would otherwise read the per-task skips). A `skip`ped /\n\t\t\t// already-stopped workflow ignores a further `stop`; a natural finish skips none of this.\n\t\t\tif (this.#cancelled(runSignal)) {\n\t\t\t\tthis.#skipFrom(workflow.phases.phases(), 0)\n\t\t\t\tif (this.#stoppable(workflow)) workflow.stop()\n\t\t\t} else if (this.#completable(workflow)) {\n\t\t\t\tworkflow.complete()\n\t\t\t}\n\t\t\treturn { workflow, status: workflow.status, results: workflow.results() }\n\t\t} finally {\n\t\t\ttimeout?.clear()\n\t\t\trunSignal?.removeEventListener('abort', onCancel)\n\t\t}\n\t}\n\n\t// Run ONE phase's tasks CONCURRENTLY through a single substrate Runner. Returns whether the\n\t// phase failed under bail-true (so `#execute` skips the rest) — `false` for a graceful\n\t// settle-all AND for a run-level cancel (which is NOT a phase failure; `#execute`'s halt\n\t// guard handles the skip + the workflow `stop`). The Runner provides bounded concurrency +\n\t// the fail-fast abort cascade; this handler only drives the live task entity.\n\tasync #runPhase(\n\t\tworkflow: WorkflowInterface,\n\t\tphase: PhaseInterface,\n\t\tdefinition: PhaseDefinition | undefined,\n\t\trunSignal: AbortSignal | undefined,\n\t\tholder: { runner: RunnerInterface<TaskInterface, void> | undefined },\n\t\tdepth: number,\n\t\tancestry: readonly string[],\n\t): Promise<boolean> {\n\t\tconst tasks = phase.tasks.tasks()\n\t\tif (tasks.length === 0) return false\n\t\t// The EFFECTIVE per-phase failure policy: the phase definition's own `bail` when it declares\n\t\t// one, else the workflow default (`effectiveBail = phase.bail ?? workflow.bail`). This single\n\t\t// line drives the halt — `bail` is threaded into every `#runTask`, so a strict phase fail-fasts\n\t\t// even under a graceful workflow, and a graceful phase settles-all even under a strict one.\n\t\tconst bail = definition?.bail ?? workflow.bail\n\t\t// Clamp a non-positive `concurrency` (a hand-built definition not validated by the contract,\n\t\t// which enforces `>= 1`, could carry `0` / negative) to the default — a non-positive throttle\n\t\t// means \"no throttle declared\" ⇒ run them all, never a broken Runner (createRunner requires a\n\t\t// positive integer, flooring at 1; passing 0 here would silently serialize, not \"run all\").\n\t\tconst concurrency =\n\t\t\tdefinition?.concurrency !== undefined && definition.concurrency > 0\n\t\t\t\t? definition.concurrency\n\t\t\t\t: DEFAULT_PHASE_CONCURRENCY\n\t\t// The substrate Queue retries a failed task by RE-INVOKING its handler (`#runTask`), so the\n\t\t// leaf must survive a failed attempt to recover on a later one. This run-local map counts each\n\t\t// task's attempts (by id) so `#runTask` can DEFER the leaf `fail` until the FINAL attempt\n\t\t// (`attempt > retries`) — an intermediate failure re-throws (driving the Queue's retry) WITHOUT\n\t\t// terminating the leaf, so a subsequent success can still `complete` it. A no-retry task's first\n\t\t// attempt IS its final one, so this reduces to today's behavior exactly. Fresh per phase run.\n\t\tconst attempts = new Map<string, number>()\n\t\tconst runner = new Runner<TaskInterface, void>({\n\t\t\tconcurrency,\n\t\t\t// Thread each task's per-entry `retries` / `timeout` overrides (Seam A) from its definition\n\t\t\t// into the substrate unit — the Part-0 resolver. The phase Runner's defaults are the\n\t\t\t// (unset) runner-level retries/timeout, so a task that declares neither behaves exactly as\n\t\t\t// before; one that declares them OVERRIDES the queue default for that unit alone.\n\t\t\tentries: (task) => {\n\t\t\t\tconst def = this.#taskOf(definition, task.id)\n\t\t\t\treturn { retries: def?.retries, timeout: def?.timeout }\n\t\t\t},\n\t\t\thandler: (controller) =>\n\t\t\t\tthis.#runTask(\n\t\t\t\t\tworkflow,\n\t\t\t\t\tcontroller.input,\n\t\t\t\t\tthis.#taskOf(definition, controller.input.id),\n\t\t\t\t\tcontroller,\n\t\t\t\t\trunSignal,\n\t\t\t\t\tbail,\n\t\t\t\t\tattempts,\n\t\t\t\t\tdepth,\n\t\t\t\t\tancestry,\n\t\t\t\t),\n\t\t})\n\t\tholder.runner = runner\n\t\ttry {\n\t\t\t// The Runner sequences + bounds the work; its ordered results are unused (the OUTCOME\n\t\t\t// lives on each live task). Under bail-true the FIRST failure rejects this — fail-fast.\n\t\t\tawait runner.execute(tasks)\n\t\t\treturn false\n\t\t} catch {\n\t\t\t// The phase Runner rejected. Two causes reject it: a bail-true fail-fast (a task threw,\n\t\t\t// so the Runner aborted the siblings) — a genuine phase failure, report `true` so\n\t\t\t// `#execute` skips the rest (the failing leaf already `fail`ed). OR a run-level cancel I\n\t\t\t// forwarded (`onCancel` → `runner.abort`) — NOT a phase failure: report `false` and let\n\t\t\t// `#execute`'s halt guard skip the remaining phases + force the workflow `stop`.\n\t\t\treturn !this.#cancelled(runSignal)\n\t\t} finally {\n\t\t\trunner.destroy()\n\t\t\tholder.runner = undefined\n\t\t}\n\t}\n\n\t// Run ONE task: drive the live entity through its transitions around a dispatch by name.\n\t// `start` (once), dispatch, then `complete(value)` on a returned value or `fail(error)` on a\n\t// FINAL-attempt failure. A genuine CANCEL (`#skipping` — a run-level bound, or a sibling's\n\t// fail-fast under bail-true) `skip`s the task instead.\n\t//\n\t// THREE abort causes reach this task's signal and MUST be told apart (the substrate folds all\n\t// three onto the attempt signal `controller.signal`):\n\t// • a per-attempt TIMEOUT (the Queue's per-entry deadline) — fires ONLY the attempt signal, never\n\t// the unit `Abort` (`controller.aborted`) nor `runSignal`;\n\t// • a SIBLING fail-fast under bail (the Runner aborts in-flight siblings on a failure) — aborts\n\t// the unit `Abort` ⇒ `controller.aborted`;\n\t// • a run-level CANCEL (abort / run-timeout / budget) — fires `runSignal` (and, forwarded through\n\t// the phase Runner's abort, the unit `Abort` too).\n\t// So `#skipping` (`controller.aborted || runSignal.aborted`) is the genuine-cancel discriminator,\n\t// and a BARE timeout is `signal.aborted && !#skipping` — a RETRYABLE FAILURE of this attempt, NOT\n\t// a skip: it joins the retry-cooperative path below (non-final ⇒ leaf stays `running` for the\n\t// Queue's own retry; final ⇒ `task.fail` so the leaf is `failed`, visible to `bail` /\n\t// `deriveWorkflowStatus`), never `#skip` (which would lose a recovered result and hide the fault).\n\t//\n\t// RETRIES: the substrate Queue re-invokes this handler per attempt (threaded `retries`), so the\n\t// leaf must survive an intermediate failure to recover. `attempts` counts this task's invocations;\n\t// an attempt that is NOT the last (`attempt <= retries`) re-throws on a thrown failure to DRIVE the\n\t// Queue's retry WITHOUT failing the leaf (it stays `running`, so a later attempt can still\n\t// `complete`); a non-final TIMEOUT likewise leaves the leaf `running` (the Queue's race already\n\t// rejected the attempt and retries it). Only the FINAL attempt records the leaf `fail`. A no-retry\n\t// task's first attempt is its final one, so the no-timeout path is byte-identical to before. On the\n\t// FINAL thrown failure: bail-true re-throws so the substrate Runner fail-fasts (aborts siblings +\n\t// rejects the phase run); bail-false swallows (the failure is recorded and the run settles all).\n\tasync #runTask(\n\t\tworkflow: WorkflowInterface,\n\t\ttask: TaskInterface,\n\t\tdefinition: TaskDefinition | undefined,\n\t\tcontroller: ControllerInterface<TaskInterface, void>,\n\t\trunSignal: AbortSignal | undefined,\n\t\tbail: boolean,\n\t\tattempts: Map<string, number>,\n\t\tdepth: number,\n\t\tancestry: readonly string[],\n\t): Promise<void> {\n\t\t// The task's folded cancellation handed to the handler: the substrate per-unit ATTEMPT signal\n\t\t// (fires on this Runner's abort — a sibling fail-fast or a run-level cancel I forwarded — OR on\n\t\t// the per-attempt deadline) ANY-combined with the run signal directly, so a handler observes\n\t\t// any cause. `createAbort` does the fold. NOTE this is broader than the genuine-cancel test:\n\t\t// `signal.aborted` is true for a bare timeout too, which is why `#skipping` (the unit-abort /\n\t\t// run-cancel discriminator) — not `signal.aborted` — gates the skip path.\n\t\tconst signal = this.#taskSignal(controller.signal, runSignal)\n\t\t// This attempt's 1-based number, and whether it is the LAST the Queue will make (the per-task\n\t\t// `retries` + 1 total; the substrate floors negative retries at 0). The leaf is failed only on\n\t\t// the final attempt, so an earlier failure/timeout leaves the leaf `running` to retry.\n\t\tconst attempt = (attempts.get(task.id) ?? 0) + 1\n\t\tattempts.set(task.id, attempt)\n\t\tconst retries = Math.max(0, definition?.retries ?? 0)\n\t\tconst last = attempt > retries\n\t\t// `start` only the FIRST time (a retry re-invokes this on the still-`running` leaf — a second\n\t\t// `start` would be an illegal `running → running` transition).\n\t\tif (task.status === 'pending') task.start()\n\t\t// A genuine CANCEL that landed BEFORE dispatch (a run-level bound, or a sibling fail-fast): skip\n\t\t// without running the handler — the run is halting. A bare per-attempt timeout cannot precede\n\t\t// dispatch (its deadline is armed as the attempt begins), so it is excluded from this skip.\n\t\tif (this.#skipping(controller, runSignal)) {\n\t\t\tthis.#skip(task)\n\t\t\treturn\n\t\t}\n\t\t// The task's open `metadata` bag is on its snapshot (the live `TaskContext` carries only\n\t\t// lineage), so read it from there — the task's input the handler may inspect.\n\t\tconst handle = new TaskController(signal, task.snapshot().metadata, task.context, () =>\n\t\t\tworkflow.results(),\n\t\t)\n\t\ttry {\n\t\t\tconst value = await this.#dispatch(definition, handle, depth, ancestry)\n\t\t\t// A genuine cancel during the handler, OR the runner already swept this task terminal on a\n\t\t\t// run-level cancel (the substrate raced this slow handler out): do NOT record a misleading\n\t\t\t// `complete` — `#skip` is a guarded no-op on an already-settled task, and skips a\n\t\t\t// still-`running` one.\n\t\t\tif (task.status !== 'running' || this.#skipping(controller, runSignal)) {\n\t\t\t\tthis.#skip(task)\n\t\t\t\treturn\n\t\t\t}\n\t\t\t// A bare per-attempt TIMEOUT (the attempt signal fired, but it was NOT a cancel): a\n\t\t\t// retryable failure of THIS attempt — retry (non-final) or `fail` the leaf (final), never a\n\t\t\t// misleading `complete` of the (discarded) post-deadline value.\n\t\t\tif (signal.aborted) {\n\t\t\t\tthis.#timedOut(task, last)\n\t\t\t\treturn\n\t\t\t}\n\t\t\ttask.complete(value)\n\t\t} catch (error) {\n\t\t\t// A handler threw. If the runner already swept this task terminal, or a genuine cancel\n\t\t\t// fired, treat it as a halt — `#skip` (guarded).\n\t\t\tif (task.status !== 'running' || this.#skipping(controller, runSignal)) {\n\t\t\t\tthis.#skip(task)\n\t\t\t\treturn\n\t\t\t}\n\t\t\t// A bare per-attempt TIMEOUT surfaced as a throw (a signal-aware handler threw on the\n\t\t\t// deadline): the retryable-failure path, same as the resolve branch above.\n\t\t\tif (signal.aborted) {\n\t\t\t\tthis.#timedOut(task, last)\n\t\t\t\treturn\n\t\t\t}\n\t\t\t// A genuine task failure (incl. a typed `DEPTH` guard rejection of an over-deep / cyclic\n\t\t\t// agent task). NOT the final attempt: re-throw to drive the Queue's retry, leaving the leaf\n\t\t\t// `running` so a later attempt can still recover (`complete`) it — the leaf is NOT failed yet.\n\t\t\tif (!last) throw error\n\t\t\t// The FINAL attempt failed: record it on the leaf.\n\t\t\ttask.fail(error)\n\t\t\t// bail-true: re-throw so the substrate Runner fail-fasts (aborts the siblings + rejects\n\t\t\t// the phase run). bail-false: swallow — the failure is recorded and the run settles all.\n\t\t\tif (bail) throw error\n\t\t}\n\t}\n\n\t// Settle a TIMED-OUT attempt (the per-attempt deadline fired) on the leaf — the retry-cooperative\n\t// path a per-attempt timeout shares with a thrown failure. NON-final: leave the leaf `running` and\n\t// return, so the Queue's own race (which already rejected this attempt on the deadline) retries it\n\t// and a later attempt can still `complete` the leaf. FINAL: `task.fail` a timeout error so the leaf\n\t// is `failed` (visible to `bail` + `deriveWorkflowStatus`) — never `skip`ped (which would hide the\n\t// fault and, on a non-final timeout, discard the recovered result). No re-throw is needed for the\n\t// substrate fail-fast under bail-true: the Queue's race already rejected the FINAL attempt's entry,\n\t// so the Runner fail-fasts (aborts siblings + rejects the phase run) regardless of this leaf write.\n\t#timedOut(task: TaskInterface, last: boolean): void {\n\t\tif (!last) return\n\t\ttask.fail(new Error(`task '${task.id}' timed out`))\n\t}\n\n\t// Dispatch a task BY NAME on its `run.via` form:\n\t// • `function` → the WorkflowFunctions registry, invoked with the TaskController.\n\t// • `tool` → the ToolManager, invoked with the task's input; a tool result's `error`\n\t// (the manager isolates a throw into one) is re-thrown so the leaf `fail`s.\n\t// • `agent` → the WorkflowAgents resolver (W-c2), behind the depth + cycle guard; the\n\t// resolved subagent runs to its result (folding the task's cancellation),\n\t// returned as the task's completed value. An over-deep / cyclic agent task\n\t// THROWS a typed `DEPTH` WorkflowError (→ the leaf `fail`s).\n\t// • not found → AUTO-COMPLETE (resolve `undefined`): the ROADMAP no-handler rule.\n\tasync #dispatch(\n\t\tdefinition: TaskDefinition | undefined,\n\t\tcontroller: TaskController,\n\t\tdepth: number,\n\t\tancestry: readonly string[],\n\t): Promise<unknown> {\n\t\tconst form = definition?.run\n\t\tif (form !== undefined && isFunctionTask(form)) {\n\t\t\tconst handler = this.#functions[form.name]\n\t\t\tif (handler !== undefined) return handler(controller)\n\t\t\treturn undefined\n\t\t}\n\t\tif (form !== undefined && isToolTask(form)) {\n\t\t\t// Bind the manager to a local so it narrows to a definite `ToolManagerInterface` — then\n\t\t\t// `tool` lookup AND `execute` are called DIRECTLY (no `?.`), so `result` is the\n\t\t\t// non-optional `ToolResult` rather than being widened by an optional chain's `undefined`.\n\t\t\tconst tools = this.#tools\n\t\t\tif (tools === undefined) return undefined\n\t\t\tconst tool = tools.tool(form.name)\n\t\t\tif (tool === undefined) return undefined\n\t\t\tconst result = await tools.execute({\n\t\t\t\tid: controller.task.id,\n\t\t\t\tname: form.name,\n\t\t\t\targuments: controller.input,\n\t\t\t})\n\t\t\t// A `tool` result NEVER throws — the manager isolates a handler throw into `result.error`.\n\t\t\t// Surface that as a task failure (so a failing tool `fail`s the leaf, honouring `bail`),\n\t\t\t// else return the value as the task's completed outcome.\n\t\t\tif (result.error !== undefined) throw new Error(result.error)\n\t\t\treturn result.value\n\t\t}\n\t\tif (form !== undefined && isAgentTask(form)) {\n\t\t\treturn this.#dispatchAgent(form.name, controller, depth, ancestry)\n\t\t}\n\t\t// An unregistered name — auto-complete.\n\t\treturn undefined\n\t}\n\n\t// Dispatch an `agent` task (W-c2): resolve the subagent, apply the depth + cycle guard, BIND\n\t// the depth/cycle-aware workflow tool onto its context (the propagation seam), fold the task's\n\t// cancellation into the run, and drive it — returning its `AgentResult` as the task's outcome.\n\t// An UNREGISTERED agent name auto-completes (no-handler rule, consistent with function/tool).\n\tasync #dispatchAgent(\n\t\tname: string,\n\t\tcontroller: TaskController,\n\t\tdepth: number,\n\t\tancestry: readonly string[],\n\t): Promise<unknown> {\n\t\tconst resolve = this.#agents\n\t\tif (resolve === undefined) return undefined\n\t\tconst agent = resolve(name)\n\t\tif (agent === undefined) return undefined\n\t\t// GUARD (before running the agent): running it would let it author + run a NESTED workflow\n\t\t// at `depth + 1`, so reject when that would exceed the bound, OR when this agent is already\n\t\t// an ancestor (a re-entry cycle). The throw becomes the leaf's typed `DEPTH` failure.\n\t\tif (depth + 1 > MAX_WORKFLOW_DEPTH) {\n\t\t\tthrow new WorkflowError('DEPTH', `agent '${name}' exceeds max workflow depth`, {\n\t\t\t\tagent: name,\n\t\t\t\tdepth,\n\t\t\t\tmax: MAX_WORKFLOW_DEPTH,\n\t\t\t})\n\t\t}\n\t\tconst tag = agentTag(name)\n\t\tif (ancestry.includes(tag)) {\n\t\t\tthrow new WorkflowError('DEPTH', `agent '${name}' is already an ancestor (cycle)`, {\n\t\t\t\tagent: name,\n\t\t\t\tancestry: [...ancestry],\n\t\t\t})\n\t\t}\n\t\t// BIND the workflow tool so the subagent can fan out into a nested workflow at `depth + 1`\n\t\t// with THIS agent added to the ancestry — the propagation across the agent/tool boundary\n\t\t// (closed over the tool at bind time, since a tool handler receives no ambient context). The\n\t\t// current workflow's id (the task's lineage) is the tool's WRAPPED default, used only on a\n\t\t// no-args call — re-running it is a cycle the guard catches, a safe default.\n\t\tthis.#bindWorkflowTool(agent, depth, [...ancestry, tag], controller.task.phase.workflow.id)\n\t\treturn this.#runAgent(agent, controller.signal)\n\t}\n\n\t// BIND the depth/cycle-aware workflow tool onto a subagent's context (under\n\t// WORKFLOW_TOOL_NAME) so it can author + run a NESTED workflow. The tool is built via the\n\t// injected `createWorkflowTool` (closing over `depth` / `ancestry`), so when the subagent\n\t// invokes it the handler runs the nested workflow at `depth + 1` with the extended ancestry —\n\t// the depth/ancestry travel through the closure, not the (context-free) tool-call boundary.\n\t// `workflowId` is the wrapped default (the agent's own current workflow), used only on a no-args\n\t// call. No-op when no binder was injected (an agent with no workflow tool still runs its turn).\n\t#bindWorkflowTool(\n\t\tagent: AgentInterface,\n\t\tdepth: number,\n\t\tancestry: readonly string[],\n\t\tworkflowId: string,\n\t): void {\n\t\tconst bind = this.#workflowTool\n\t\tif (bind === undefined) return\n\t\tconst wrapped: WorkflowDefinition = { id: workflowId, name: workflowId, phases: [] }\n\t\tagent.context.tools.add(bind(wrapped, this, { depth, ancestry }))\n\t}\n\n\t// Run a resolved subagent to its settled `AgentResult`, folding the task's cancellation: an\n\t// already-aborted signal cancels the agent up front; otherwise a one-shot listener fires\n\t// `agent.abort(reason)` when the workflow cancels (so a run-level / sibling cancel stops the\n\t// subagent). `generate()` RESOLVES a partial on a cancel (never rejects), so a cancelled\n\t// subagent settles — the caller's post-dispatch `signal.aborted` check then `skip`s the task.\n\tasync #runAgent(agent: AgentInterface, signal: AbortSignal): Promise<unknown> {\n\t\tconst onAbort = (): void => agent.abort(signal.reason)\n\t\tif (signal.aborted) {\n\t\t\tagent.abort(signal.reason)\n\t\t} else {\n\t\t\tsignal.addEventListener('abort', onAbort, { once: true })\n\t\t}\n\t\ttry {\n\t\t\treturn await agent.generate()\n\t\t} finally {\n\t\t\tsignal.removeEventListener('abort', onAbort)\n\t\t}\n\t}\n\n\t// The per-task folded signal: ANY-combine the substrate per-unit signal with the run signal\n\t// (when present), via the shipped `createAbort` parent-linking (`AbortSignal.any`). No\n\t// hand-rolled listener wiring — the abort primitive owns the fold.\n\t#taskSignal(unitSignal: AbortSignal, runSignal: AbortSignal | undefined): AbortSignal {\n\t\tif (runSignal === undefined) return unitSignal\n\t\tconst abort: AbortInterface = createAbort({ signal: AbortSignal.any([unitSignal, runSignal]) })\n\t\treturn abort.signal\n\t}\n\n\t// Fold the run-level bounds into ONE signal — the external `signal`, the deadline, and the\n\t// budget combined via `AbortSignal.any` (the agent runtime's `#parents` pattern). A lone\n\t// present bound is returned directly; none ⇒ `undefined` (no run-level cancellation).\n\t#fold(\n\t\toptions: WorkflowRunOptions | undefined,\n\t\ttimeout: TimeoutInterface | undefined,\n\t): AbortSignal | undefined {\n\t\tconst signals: AbortSignal[] = []\n\t\tif (options?.signal !== undefined) signals.push(options.signal)\n\t\tif (timeout !== undefined) signals.push(timeout.signal)\n\t\tif (options?.budget !== undefined) signals.push(options.budget.signal)\n\t\tif (signals.length === 0) return undefined\n\t\tif (signals.length === 1) return signals[0]\n\t\treturn AbortSignal.any(signals)\n\t}\n\n\t// Skip every not-yet-settled task across phases `index..end` — the halt path (a run-level\n\t// cancel, or the remaining phases after a bail-true failure). Only a `pending` / `running`\n\t// task can `skip` (a settled one ignores it), so this is safe over already-finished phases.\n\t#skipFrom(phases: readonly PhaseInterface[], index: number): void {\n\t\tfor (let cursor = index; cursor < phases.length; cursor += 1) {\n\t\t\tconst phase = phases[cursor]\n\t\t\tif (phase === undefined) continue\n\t\t\tfor (const task of phase.tasks.tasks()) this.#skip(task)\n\t\t}\n\t}\n\n\t// Skip one task iff it is not already terminal — a settled leaf has no legal `skip`\n\t// transition (it would throw a `TRANSITION` WorkflowError), so guard on the live status.\n\t#skip(task: TaskInterface): void {\n\t\tif (task.status === 'pending' || task.status === 'running') task.skip()\n\t}\n\n\t// Whether an in-flight task is being GENUINELY CANCELLED (and so should `skip`), as opposed to\n\t// merely TIMED OUT (which retries / fails). Three causes can fire a task's attempt signal; only\n\t// two are cancels: the unit `Abort` — `controller.aborted` — fired by a SIBLING fail-fast under\n\t// bail OR by a run-level cancel I forwarded through the phase Runner's abort; and the run signal\n\t// directly (`runSignal.aborted`). A per-attempt TIMEOUT fires NEITHER (it aborts only the deadline\n\t// portion of the attempt signal, never the unit `Abort` nor the run signal), so it is excluded —\n\t// the precise discriminator that keeps a timeout off the skip path. A fresh read each call so it\n\t// reflects a cancel that landed mid-dispatch.\n\t#skipping(\n\t\tcontroller: ControllerInterface<TaskInterface, void>,\n\t\trunSignal: AbortSignal | undefined,\n\t): boolean {\n\t\treturn controller.aborted || runSignal?.aborted === true\n\t}\n\n\t// Whether the run-level signal has fired (a fresh read, so it reflects an abort that landed\n\t// during a phase) — `false` when there is no run signal at all.\n\t#cancelled(runSignal: AbortSignal | undefined): boolean {\n\t\treturn runSignal?.aborted === true\n\t}\n\n\t// Whether the workflow is no longer runnable — its derived status has reached a terminal\n\t// state (a bail-true failure flipped it to `failed`, or a force `skip` / `stop`), so the\n\t// remaining phases must not start.\n\t#halted(workflow: WorkflowInterface): boolean {\n\t\tconst status = workflow.status\n\t\treturn status === 'failed' || status === 'skipped' || status === 'stopped'\n\t}\n\n\t// Whether a run-level cancel should force `stop` — yes UNLESS the workflow already settled a\n\t// genuine `failed` (a bail-true failure: preserve it, never mask it with `stopped`) or is\n\t// ALREADY `stopped` (idempotent). A `skipped` derived status is the CONSEQUENCE of the\n\t// runner's own per-task skips on the cancel path, so `stop` SHOULD supersede it (the\n\t// override wins) — the workflow settles `stopped`, the true outcome of a cancelled run.\n\t#stoppable(workflow: WorkflowInterface): boolean {\n\t\tconst status = workflow.status\n\t\treturn status !== 'failed' && status !== 'stopped'\n\t}\n\n\t// A NATURALLY-finished run that still derives `pending` executed but recorded NO work (zero phases,\n\t// or all phases empty / no-op) — vacuously done ⇒ force `completed`. Gated on EXACTLY `pending` so a\n\t// real `completed`, a bail-true `failed`, a `stopped`, or a derived `skipped` is never overridden.\n\t#completable(workflow: WorkflowInterface): boolean {\n\t\treturn workflow.status === 'pending'\n\t}\n\n\t// Correlate a live phase to its definition by positional `id` — the source of its\n\t// `concurrency`. `undefined` when the definition has no matching phase (defensive — the\n\t// caller passes the SAME definition the tree was built from).\n\t#phaseOf(definition: WorkflowDefinition, id: string): PhaseDefinition | undefined {\n\t\treturn definition.phases.find((phase) => phase.id === id)\n\t}\n\n\t// Correlate a live task to its definition by positional `id` within its phase — the source\n\t// of its `run` form. `undefined` ⇒ the no-handler auto-complete path in `#dispatch`.\n\t#taskOf(phase: PhaseDefinition | undefined, id: string): TaskDefinition | undefined {\n\t\treturn phase?.tasks.find((task) => task.id === id)\n\t}\n}\n","import type { RunnerInterface, RunnerOptions, SchedulerInterface } from './types.js'\nimport { Scheduler } from './Scheduler.js'\nimport type { ContractInterface } from '@orkestrel/contract'\nimport type { ToolInterface } from '@orkestrel/agent'\nimport type { DriverInterface, TableInterface } from '@orkestrel/database'\nimport type {\n\tWorkflowDefinition,\n\tWorkflowDraft,\n\tWorkflowInterface,\n\tWorkflowOptions,\n\tWorkflowRunnerInterface,\n\tWorkflowRunnerOptions,\n\tWorkflowSnapshot,\n\tWorkflowSnapshotRow,\n\tWorkflowSteps,\n\tWorkflowStoreInterface,\n\tWorkflowToolOptions,\n} from './types.js'\nimport { createTool } from '@orkestrel/agent'\nimport { createContract, rawShape, schemaToParameters, stringShape } from '@orkestrel/contract'\nimport { createDatabase, createMemoryDriver } from '@orkestrel/database'\nimport {\n\tDEFAULT_BAIL,\n\tMAX_WORKFLOW_DEPTH,\n\tPHASE_STATUSES,\n\tTASK_STATUSES,\n\tWORKFLOW_STATUSES,\n\tWORKFLOW_TOOL_DESCRIPTION,\n\tWORKFLOW_TOOL_NAME,\n} from './constants.js'\nimport { WorkflowError } from './errors.js'\nimport {\n\tcompleteDraft,\n\tdefinitionToSnapshot,\n\texpandSteps,\n\tworkflowTag,\n\tworkflowToolSummary,\n} from './helpers.js'\nimport { workflowDraftShape, workflowShape, workflowStepsShape } from './shapers.js'\nimport { DatabaseWorkflowStore } from './stores/DatabaseWorkflowStore.js'\nimport { MemoryWorkflowStore } from './stores/MemoryWorkflowStore.js'\nimport { Workflow } from './Workflow.js'\nimport { WorkflowRunner } from './WorkflowRunner.js'\nimport { Runner } from './Runner.js'\n\n// Workflow contract factory — compiles the workflow shape (shapers.ts) into the\n// four lockstep outputs (JSON Schema + guard + parser + generator) and types the\n// result as the hand-written `WorkflowDefinition` (the source of truth, AGENTS §14).\n//\n// The compiled `ContractInterface<Infer<typeof workflowShape>>` is structurally\n// identical to `ContractInterface<WorkflowDefinition>` — verified bidirectionally,\n// with ZERO TS2589 (the three-level nesting that tripped the databases module's\n// `objectShape` generics does NOT strike here, because the shapes are kept\n// intersection-free per the shapers' design note). So the hand-written interface\n// stays the source of truth AND the contract's `is` / `generate` / `parse` narrow\n// to it natively — no `as`. The round-trip parity test (generate → is → parse)\n// guards against any future drift between the two.\n//\n// `parse` is the contract's own parser, used directly: the shared compiler now\n// re-applies each leaf's `min` / `max` / `pattern` refinement after coercion\n// (compilers.ts `compileParser`, via the shared `stringOf` / `boundsOf`\n// combinators), so a parsed\n// `WorkflowDefinition` already satisfies `is` — refinements included (AGENTS §14\n// parse↔guard soundness). An empty `id` or `concurrency: 0` parses to `undefined`\n// at the contract level, so no guard-gate wrapper is needed here.\n\n/**\n * Compile the workflow definition contract — the JSON Schema, guard, parser, and\n * seeded generator for a {@link WorkflowDefinition}, all derived from one shape and\n * kept in lockstep.\n *\n * @remarks\n * The returned {@link ContractInterface}:\n * - `schema` — the emitted JSON Schema for a workflow definition.\n * - `is` — a total guard that narrows `unknown` to a valid {@link WorkflowDefinition}\n * (malformed input returns `false`, never throws).\n * - `parse` — coerces `unknown` to a {@link WorkflowDefinition}, or `undefined` when\n * it does not match.\n * - `generate` — produces a deterministic valid {@link WorkflowDefinition} from an\n * optional seeded random source.\n *\n * @returns The compiled {@link WorkflowDefinition} contract\n *\n * @example\n * ```ts\n * import { createWorkflowContract } from '@src/core'\n *\n * const contract = createWorkflowContract()\n * const definition = contract.generate() // a valid WorkflowDefinition\n * contract.is(definition) // true\n * contract.parse({ id: '', phases: [] }) // undefined (malformed)\n * ```\n */\nexport function createWorkflowContract(): ContractInterface<WorkflowDefinition> {\n\tconst contract = createContract(workflowShape)\n\treturn {\n\t\tschema: contract.schema,\n\t\tis: contract.is,\n\t\tgenerate: (random) => contract.generate(random),\n\t\t// The contract's own parser already enforces every leaf refinement (it\n\t\t// re-applies the shared `stringOf` / `boundsOf` combinators after coercion),\n\t\t// so a non-`undefined` result satisfies `is` — no guard-gate wrapper needed.\n\t\tparse: (value) => contract.parse(value),\n\t}\n}\n\n/**\n * Compile the LENIENT workflow DRAFT contract — identical to\n * {@link createWorkflowContract} EXCEPT `id` and `name` are OPTIONAL at all three levels\n * (workflow / phase / task), so a small model can omit the six identity strings.\n *\n * @remarks\n * The widened authoring surface {@link createWorkflowTool} parses an authored blob through\n * before {@link import('./helpers.js').completeDraft} fills the missing ids/names. It does\n * NOT relax the canonical contract — {@link createWorkflowContract} stays byte-for-byte\n * unchanged and STRICT, and the completed draft is re-validated against THAT strict gate\n * before running (soundness preserved). A PROVIDED `id` / `name` still carries `minLength: 1`,\n * so an explicitly-empty `id: ''` is REJECTED (parses to `undefined`), never auto-filled —\n * keeping \"garbage\" distinct from \"omitted\". `run` stays required.\n *\n * @returns The compiled {@link WorkflowDraft} contract\n *\n * @example\n * ```ts\n * import { createWorkflowDraftContract, completeDraft } from '@src/core'\n *\n * const draft = createWorkflowDraftContract()\n * const parsed = draft.parse({ phases: [{ tasks: [{ run: { via: 'function', name: 'f' } }] }] })\n * const definition = parsed && completeDraft(parsed) // ids/names filled positionally\n * draft.parse({ id: '', phases: [] }) // undefined — an explicit empty id is rejected\n * ```\n */\nexport function createWorkflowDraftContract(): ContractInterface<WorkflowDraft> {\n\tconst contract = createContract(workflowDraftShape)\n\treturn {\n\t\tschema: contract.schema,\n\t\tis: contract.is,\n\t\tgenerate: (random) => contract.generate(random),\n\t\tparse: (value) => contract.parse(value),\n\t}\n}\n\n/**\n * Build the live W-b entity tree from a {@link WorkflowDefinition} — the whole\n * {@link WorkflowInterface} → {@link import('./types.js').PhaseInterface} →\n * {@link import('./types.js').TaskInterface} tree, each level wired with its lineage\n * context, its emitter, and the cascade.\n *\n * @remarks\n * The definition is the DECLARATIVE blueprint; this seeds an initial all-`pending`\n * {@link WorkflowSnapshot} from it ({@link definitionToSnapshot}) and constructs the live\n * tree over that one path. The `bail` failure policy resolves to `options.bail`, else the\n * definition's `bail`, else the graceful {@link import('./constants.js').DEFAULT_BAIL}; it\n * feeds {@link import('./helpers.js').deriveWorkflowStatus}. Per-phase / per-task initial\n * listeners + metadata travel through `options.phases[id].on` /\n * `options.phases[id].tasks[id]` (the AGENTS §8 nested-by-id bag). The W-b tree is the\n * state machine ONLY — it does not execute tasks (W-c drives the transitions).\n *\n * @param definition - The workflow definition to bring to life\n * @param options - Runtime options (initial listeners, `bail` override, per-node options)\n * @returns The live {@link WorkflowInterface} root\n *\n * @example\n * ```ts\n * import { createWorkflow } from '@src/core'\n *\n * const workflow = createWorkflow(definition, { on: { complete: () => done() } })\n * const phase = workflow.phase('phase-build')\n * phase?.task('task-compile')?.start() // pending → running (cascades up)\n * ```\n */\nexport function createWorkflow(\n\tdefinition: WorkflowDefinition,\n\toptions?: WorkflowOptions,\n): WorkflowInterface {\n\tconst bail = options?.bail ?? definition.bail ?? DEFAULT_BAIL\n\t// Seed BOTH tiers of the snapshot with the effective bail (`definitionToSnapshot`'s second arg),\n\t// so an `options.bail` override reaches each INHERITING phase's snapshot while a phase with its own\n\t// `bail` still wins (`phase.bail ?? bail`) — the per-phase-bail-aware derivation reads each\n\t// PhaseSnapshot's bail. `options` is forwarded UNCHANGED (NOT `{ ...options, bail }`): the snapshot\n\t// already carries the resolved bail at both tiers, so `Workflow` reads `#bail` from it; injecting a\n\t// resolved `bail` here would make `Workflow` treat it as an EXPLICIT uniform override and clobber\n\t// per-phase overrides. A caller's genuine `options.bail` stays in `options` and cascades (uniform re-run).\n\treturn new Workflow(definitionToSnapshot(definition, bail), options)\n}\n\n/**\n * Rebuild an equivalent live W-b entity tree from a {@link WorkflowSnapshot} — the\n * inverse of {@link WorkflowInterface.snapshot}, restoring structure + each node's status\n * + recorded results + positional order + the persisted `#override`.\n *\n * @remarks\n * Round-trip fidelity is paramount: a `snapshot()` → `restoreWorkflow()` reproduces the\n * same status at every node (each `#override` restored DIRECTLY from the snapshot's own\n * `override` field, not guessed from a status divergence), the same recorded\n * {@link import('./types.js').TaskResult}s, and the same positional order (an interior\n * `skip` / `remove` survives). The snapshot is SELF-CONTAINED — it persists the `bail`\n * policy it ran under, so the restore re-derives status IDENTICALLY without a silent\n * default; the snapshot's `bail` is the source of truth, while an explicit `options.bail`\n * still wins when supplied (to deliberately re-run under a different policy). A structurally\n * invalid snapshot (a status — or override — outside the lifecycle vocabulary, or a\n * non-boolean `bail`) throws a `RESTORE` {@link WorkflowError}.\n *\n * @param snapshot - The snapshot to restore (carries its own `bail` + `override`)\n * @param options - Runtime options (initial listeners, an optional `bail` override, per-node options)\n * @returns The restored live {@link WorkflowInterface} root\n *\n * @example\n * ```ts\n * import { restoreWorkflow } from '@src/core'\n *\n * const restored = restoreWorkflow(workflow.snapshot()) // bail comes from the snapshot\n * restored.status === workflow.status // true\n * ```\n */\nexport function restoreWorkflow(\n\tsnapshot: WorkflowSnapshot,\n\toptions?: WorkflowOptions,\n): WorkflowInterface {\n\tassertSnapshot(snapshot)\n\treturn new Workflow(snapshot, options)\n}\n\n/**\n * Assert that a {@link WorkflowSnapshot} carries a `boolean` `bail` — at the workflow tier AND\n * on every phase — and that its every node's status (and its `override`, when present) is drawn\n * from the lifecycle vocabulary, throwing a `RESTORE` {@link WorkflowError} otherwise.\n *\n * @remarks\n * The boundary-narrowing guard (AGENTS §14) for {@link restoreWorkflow}: a snapshot is\n * untrusted JSON, so a status (or an override) outside\n * {@link import('./constants.js').WORKFLOW_STATUSES} /\n * {@link import('./constants.js').PHASE_STATUSES} / {@link import('./constants.js').TASK_STATUSES},\n * or a non-boolean `bail` (the workflow's OR any phase's — both are REQUIRED persisted policy),\n * is rejected loudly (naming the offending node) rather than silently producing a broken tree.\n * The `override` is optional, so it is only checked WHEN present. Structural shape beyond these\n * fields is the contract's concern; this guards exactly the fields the live state machine reads back.\n *\n * @param snapshot - The snapshot to validate\n */\nexport function assertSnapshot(snapshot: WorkflowSnapshot): void {\n\tif (typeof snapshot.bail !== 'boolean') {\n\t\tthrow new WorkflowError('RESTORE', `workflow '${snapshot.id}' has a non-boolean bail`, {\n\t\t\tworkflow: snapshot.id,\n\t\t\tbail: snapshot.bail,\n\t\t})\n\t}\n\tif (!WORKFLOW_STATUSES.includes(snapshot.status)) {\n\t\tthrow new WorkflowError('RESTORE', `workflow '${snapshot.id}' has an invalid status`, {\n\t\t\tworkflow: snapshot.id,\n\t\t\tstatus: snapshot.status,\n\t\t})\n\t}\n\tif (snapshot.override !== undefined && !WORKFLOW_STATUSES.includes(snapshot.override)) {\n\t\tthrow new WorkflowError('RESTORE', `workflow '${snapshot.id}' has an invalid override`, {\n\t\t\tworkflow: snapshot.id,\n\t\t\toverride: snapshot.override,\n\t\t})\n\t}\n\tfor (const phase of snapshot.phases) {\n\t\tif (typeof phase.bail !== 'boolean') {\n\t\t\tthrow new WorkflowError('RESTORE', `phase '${phase.id}' has a non-boolean bail`, {\n\t\t\t\tphase: phase.id,\n\t\t\t\tbail: phase.bail,\n\t\t\t})\n\t\t}\n\t\tif (!PHASE_STATUSES.includes(phase.status)) {\n\t\t\tthrow new WorkflowError('RESTORE', `phase '${phase.id}' has an invalid status`, {\n\t\t\t\tphase: phase.id,\n\t\t\t\tstatus: phase.status,\n\t\t\t})\n\t\t}\n\t\tif (phase.override !== undefined && !PHASE_STATUSES.includes(phase.override)) {\n\t\t\tthrow new WorkflowError('RESTORE', `phase '${phase.id}' has an invalid override`, {\n\t\t\t\tphase: phase.id,\n\t\t\t\toverride: phase.override,\n\t\t\t})\n\t\t}\n\t\tfor (const task of phase.tasks) {\n\t\t\tif (!TASK_STATUSES.includes(task.status)) {\n\t\t\t\tthrow new WorkflowError('RESTORE', `task '${task.id}' has an invalid status`, {\n\t\t\t\t\ttask: task.id,\n\t\t\t\t\tstatus: task.status,\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Create the in-memory durable {@link WorkflowStoreInterface} — a process-lifetime\n * {@link MemoryWorkflowStore} persisting {@link WorkflowSnapshot}s by workflow id, the DEFAULT\n * backend behind the W-d persistence seam.\n *\n * @remarks\n * The snapshot analogue of the server package's `createMemorySessionStore`\n * (and the {@link createMemoryQueueStore} family), but LEANER — there is no idle-TTL, so no\n * options bag (AGENTS §21 minimal): a persisted run-state lives until an explicit `delete`. This is\n * the zero-plumbing DEFAULT (a plain `Map`); its driver-pluggable twin is\n * {@link createDatabaseWorkflowStore} (the snapshot as one opaque JSON column over a `databases`\n * table) — for a DURABLE store (run-state surviving a restart) pass it a JSON / SQLite / IndexedDB\n * driver, and it swaps in WITHOUT touching the runner or the entity tree. Restore stays a caller\n * concern: read a snapshot back and rebuild the live tree with {@link restoreWorkflow}.\n *\n * @returns A memory-backed {@link WorkflowStoreInterface}\n *\n * @example\n * ```ts\n * import { createMemoryWorkflowStore, createWorkflow, restoreWorkflow } from '@src/core'\n *\n * const store = createMemoryWorkflowStore()\n * const workflow = createWorkflow(definition)\n * await store.set(workflow.snapshot()) // persist the run state\n * const snapshot = await store.get(definition.id)\n * const restored = snapshot && restoreWorkflow(snapshot) // an identical live tree\n * ```\n */\nexport function createMemoryWorkflowStore(): WorkflowStoreInterface {\n\treturn new MemoryWorkflowStore()\n}\n\n/**\n * Create a {@link DatabaseWorkflowStore} over any {@link DriverInterface} — the durable,\n * driver-pluggable backing for the W-d persistence seam, the opt-in twin of\n * {@link createMemoryWorkflowStore}.\n *\n * @remarks\n * Builds a one-table database (`snapshots`, keyed by `id`) over the supplied driver, the snapshot\n * held as ONE OPAQUE JSON COLUMN — the column map is `{ id; snapshot }` where `snapshot` is a\n * `rawShape` (a JSON blob), exactly as {@link createDatabaseQueueStore} stores its `input`. The\n * snapshot is already a COMPLETE, self-contained, pure-JSON payload, so storing it whole is lossless\n * AND keeps the row type FLAT — a structured multi-column snapshot table would force the contract to\n * `Infer` the deeply-nested snapshot shape (workflow → phases → tasks → results) and trip TS2589;\n * the opaque column sidesteps it (the column reads back as `unknown`, narrowed on `get` by\n * {@link import('./helpers.js').isWorkflowSnapshot}). The `driver` DEFAULTS to\n * {@link createMemoryDriver}, so the store ALSO works in memory out of the box; pass a server\n * `createJSONDriver` / `createSQLiteDriver` (or a browser IndexedDB driver) for a persistent one —\n * the durability is the driver's job, the store engine is shared. It swaps in behind\n * {@link WorkflowStoreInterface} WITHOUT touching the runner or the entity tree.\n *\n * @param driver - The storage backend the snapshots persist to (defaults to {@link createMemoryDriver})\n * @returns A {@link WorkflowStoreInterface} over the driver\n *\n * @example\n * ```ts\n * import { createDatabaseWorkflowStore, createMemoryDriver, createWorkflow, restoreWorkflow } from '@src/core'\n *\n * const store = createDatabaseWorkflowStore(createMemoryDriver()) // a durable driver swaps in here\n * const workflow = createWorkflow(definition)\n * await store.set(workflow.snapshot()) // persist the run state (one JSON column)\n * const snapshot = await store.get(definition.id)\n * const restored = snapshot && restoreWorkflow(snapshot) // an identical live tree\n * ```\n */\nexport function createDatabaseWorkflowStore(\n\tdriver: DriverInterface = createMemoryDriver(),\n): WorkflowStoreInterface {\n\t// The snapshot is stored as ONE OPAQUE JSON column (`rawShape`), so the row infers FLAT —\n\t// `{ id: string; snapshot: unknown }` = `WorkflowSnapshotRow` — and the deeply-nested snapshot\n\t// shape never forces a contract `Infer` (the TS2589 trap a structured table would spring).\n\tconst columns = { id: stringShape(), snapshot: rawShape({}) }\n\tconst database = createDatabase({ driver, tables: { snapshots: columns } })\n\tconst table: TableInterface<WorkflowSnapshotRow> = database.table('snapshots')\n\treturn new DatabaseWorkflowStore(table)\n}\n\n/**\n * Create a workflow runner — a {@link WorkflowRunnerInterface} that EXECUTES a live W-b\n * workflow tree by COMPOSING the shipped substrate: phases sequential, tasks concurrent,\n * each task dispatched BY NAME under the workflow's `bail` policy.\n *\n * @remarks\n * The runner is THIN — it re-implements no concurrency / retry / abort logic. Per-phase\n * bounded concurrency is one {@link createRunner} per phase;\n * `bail` maps onto that Runner's fail-fast (`true` — the first failure aborts the in-flight\n * siblings + skips the rest) vs settle-all (`false` — failures are recorded, the run\n * finishes); the run-level abort / timeout / budget ({@link import('./types.js').WorkflowRunOptions})\n * fold through `AbortSignal.any` (the agent runtime's pattern); pacing is the shipped\n * scheduler. `execute(definition, options?)` BUILDS the live tree from the definition itself\n * (via {@link createWorkflow} — one source of truth, returned in `WorkflowResult.workflow`),\n * drives the live entity (`start` → `complete` / `fail`), and resolves a\n * {@link import('./types.js').WorkflowResult}.\n *\n * A task is dispatched on its {@link import('./types.js').TaskForm}: `function` → the\n * `functions` registry, `tool` → the `tools` {@link ToolManagerInterface}, `agent` → the\n * `agents` {@link import('./types.js').WorkflowAgents} resolver (W-c2), behind a depth + cycle\n * guard. A task whose handler is NOT found (an unregistered name for ANY form) AUTO-COMPLETES\n * (the ROADMAP no-handler rule).\n *\n * The runner is constructed with a reference to {@link createWorkflowTool} (the workflow-tool\n * binder) so it can BIND a depth/cycle-aware workflow tool onto a dispatched subagent's context\n * — the propagation seam — WITHOUT this module's classes importing its own `factories.ts` (the\n * factories→classes direction; the binder is injected as a value at construction).\n *\n * @param options - The behavior registries (`functions` / `tools` / `agents`) the runner\n * dispatches a task by name through, plus an optional pacing `scheduler` (default the shipped\n * cross-environment one). Omitting `functions` / `tools` / `agents` makes those task forms\n * auto-complete (no handler). See {@link WorkflowRunnerOptions}.\n * @returns A working {@link WorkflowRunnerInterface}\n *\n * @example\n * ```ts\n * import { createWorkflowRunner, createToolManager } from '@src/core'\n *\n * const tools = createToolManager()\n * const runner = createWorkflowRunner({\n * \tfunctions: { compile: async (controller) => `built ${controller.task.id}` },\n * \ttools,\n * })\n * const definition = { id: 'w', name: 'W', phases: [{ id: 'p', name: 'P', tasks: [\n * \t{ id: 't', name: 'T', run: { via: 'function', name: 'compile' } },\n * ] }] }\n * const result = await runner.execute(definition) // builds + drives the tree\n * result.status // 'completed'\n * result.workflow.phase('p')?.task('t')?.status // 'completed'\n * ```\n */\nexport function createWorkflowRunner(options?: WorkflowRunnerOptions): WorkflowRunnerInterface {\n\treturn new WorkflowRunner(\n\t\toptions?.functions ?? {},\n\t\toptions?.tools,\n\t\toptions?.agents,\n\t\toptions?.scheduler ?? createScheduler(),\n\t\tcreateWorkflowTool,\n\t)\n}\n\n/**\n * Wrap a {@link WorkflowDefinition} as an LLM-callable {@link ToolInterface} — it ADVERTISES\n * the SIMPLE flat authoring shape (`{ name?, steps: [{ name, via? }] }`) as its `parameters` so\n * even a small model can author a complete tree, and its handler EXPANDS / COMPLETES the\n * authored blob, validates it against the STRICT contract, runs it through `runner`, and\n * returns the run SUMMARY (throwing a typed {@link WorkflowError} on failure).\n *\n * @remarks\n * A plain {@link ToolManagerInterface}-compatible tool (so `createMCPServer` / `createMCPRoutes`\n * expose it for free — nothing MCP is wired here). It is ALSO the propagation carrier the\n * {@link WorkflowRunner} binds onto a dispatched subagent (W-c2): because a tool handler receives\n * ONLY the model-supplied `args` (no ambient context, no signal), the run's depth + ancestry are\n * CLOSED OVER at bind time via {@link WorkflowToolOptions}, and the handler runs the nested\n * workflow at `depth + 1` with the extended ancestry.\n *\n * **Widened authoring surface (additive — the canonical contract + runner stay STRICT and\n * unchanged).** A 2B model reliably CALLS the tool but cannot reliably emit the full four-level\n * nested {@link WorkflowDefinition} (six required `id`/`name` strings, a nested tagged union,\n * all-or-nothing). So the tool ACCEPTS three authoring forms and converges them on the SAME\n * strict {@link createWorkflowContract} gate before running (soundness preserved):\n * - the FLAT shape `{ name?, steps: [{ name, via? }] }` — the ADVERTISED `parameters` (the simplest\n * form, {@link import('./helpers.js').expandSteps}'d into one one-task phase per step);\n * - a nested DRAFT with any `id`/`name` OMITTED — {@link createWorkflowDraftContract}-parsed then\n * {@link import('./helpers.js').completeDraft}'d (missing ids synthesized positionally);\n * - the full nested {@link WorkflowDefinition} — the advanced escape-hatch (documented in the\n * description), accepted as the draft super-set.\n *\n * The handler conforms to the universal tool-handler contract (AGENTS §14): it returns the PLAIN\n * run-summary VALUE on success and THROWS a typed {@link WorkflowError} on every failure path. It\n * does NOT build a {@link ToolResult} itself — the `@orkestrel/agent` package's `ToolManager`\n * performs the ONE canonical wrap (`{ id, name, value }` on a return; `{ id, name, error }` on a\n * throw, ISOLATED so nothing escapes the run), so the outcome appears EXACTLY ONCE, identically,\n * over BOTH the agent loop and MCP (a throw → MCP `isError: true`):\n * - **No authored args** (an empty `arguments`) ⇒ runs the WRAPPED `definition`.\n * - **A `steps` array** ⇒ the FLAT form: parse it, {@link import('./helpers.js').expandSteps} it.\n * - **Otherwise** ⇒ the nested form: {@link createWorkflowDraftContract}-parse it,\n * {@link import('./helpers.js').completeDraft} it.\n * - **Strict gate** ⇒ the expanded / completed result is validated against\n * {@link createWorkflowContract}.`is`; a blob that can't expand, or whose result fails the strict\n * gate (e.g. an explicit empty `id`, `concurrency: 0`) ⇒ THROW a `TOOL` {@link WorkflowError} (no run).\n * - **Over-deep / cyclic** ⇒ THROW a `DEPTH` {@link WorkflowError} when the nested run would exceed\n * {@link MAX_WORKFLOW_DEPTH}, or the target workflow id is already an ancestor (a cycle) — the\n * same `code` the agent-task guard raises.\n * - **Otherwise** ⇒ `runner.execute(target, { depth: depth + 1, ancestry: … })`, RETURNING the\n * plain summary of the terminal run (`{ status, count }`, via {@link workflowToolSummary}).\n *\n * @param definition - The workflow the tool runs when called with no authored args\n * @param runner - The {@link WorkflowRunnerInterface} that executes the (nested) workflow\n * @param options - The depth + ancestry to run the nested workflow under (see\n * {@link WorkflowToolOptions}); omitted ⇒ depth `0` / empty ancestry (a top-level wrap)\n * @returns A {@link ToolInterface} (named {@link import('./constants.js').WORKFLOW_TOOL_NAME})\n * whose `parameters` advertise the FLAT authoring schema (the nested form stays accepted)\n *\n * @example\n * ```ts\n * import { createWorkflowRunner, createWorkflowTool, createToolManager } from '@src/core'\n *\n * const runner = createWorkflowRunner()\n * const tool = createWorkflowTool(definition, runner)\n * const tools = createToolManager()\n * tools.add(tool) // a model can now author + run a workflow in one call\n * ```\n */\nexport function createWorkflowTool(\n\tdefinition: WorkflowDefinition,\n\trunner: WorkflowRunnerInterface,\n\toptions?: WorkflowToolOptions,\n): ToolInterface {\n\tconst strict = createWorkflowContract()\n\tconst draft = createWorkflowDraftContract()\n\tconst steps: ContractInterface<WorkflowSteps> = createContract(workflowStepsShape)\n\tconst depth = options?.depth ?? 0\n\tconst ancestry = options?.ancestry ?? []\n\t// The tool ADVERTISES the FLAT authoring shape (the simplest surface a small model can\n\t// fill) — its JSON Schema, narrowed to the open tool-parameters record (§14, never `as`) via\n\t// the shared `schemaToParameters` contracts helper. The full nested form is STILL accepted (the\n\t// handler branches on the args' shape) but is documented in the description as the advanced\n\t// escape-hatch.\n\tconst parameters = schemaToParameters(steps.schema)\n\treturn createTool({\n\t\tname: WORKFLOW_TOOL_NAME,\n\t\tdescription: WORKFLOW_TOOL_DESCRIPTION,\n\t\tparameters,\n\t\t// The universal tool-handler contract (§14): RETURN the plain run summary on success;\n\t\t// THROW a typed WorkflowError on every failure path, which the ToolManager ISOLATES into\n\t\t// the canonical tool result's top-level `error` (so nothing escapes the run and the\n\t\t// outcome appears once, identically, over the agent loop AND MCP). The authoring surface\n\t\t// is WIDENED at this boundary ONLY (the canonical contract + runner stay strict): empty\n\t\t// args ⇒ the wrapped definition; a `steps` array ⇒ the FLAT form (expandSteps); else the\n\t\t// nested DRAFT form (draft-parse + completeDraft). EVERY path then converges on the STRICT\n\t\t// `createWorkflowContract().is` gate — a blob that can't expand / complete, or whose result\n\t\t// fails the strict gate, ⇒ throw `TOOL` (no run); an over-deep / cyclic nested run ⇒ throw\n\t\t// `DEPTH`; otherwise run at depth + 1 and return the terminal run's summary.\n\t\texecute: async (args) => {\n\t\t\t// Branch on the authored args' SHAPE (no ambient context — a tool handler gets only\n\t\t\t// `args`): empty ⇒ the wrapped definition; a `steps` array ⇒ the FLAT form, parsed +\n\t\t\t// expanded; otherwise the nested DRAFT form, parsed + completed. A parse failure leaves\n\t\t\t// `target` undefined ⇒ the strict gate below throws `TOOL`.\n\t\t\tlet target: WorkflowDefinition | undefined\n\t\t\tif (Object.keys(args).length === 0) {\n\t\t\t\ttarget = definition\n\t\t\t} else if (Array.isArray(args.steps)) {\n\t\t\t\tconst flat = steps.parse(args)\n\t\t\t\ttarget = flat === undefined ? undefined : expandSteps(flat)\n\t\t\t} else {\n\t\t\t\tconst parsed = draft.parse(args)\n\t\t\t\ttarget = parsed === undefined ? undefined : completeDraft(parsed)\n\t\t\t}\n\t\t\t// The SOUNDNESS gate: whatever authoring form produced `target`, it must satisfy the\n\t\t\t// STRICT canonical contract before it runs — the leniency never reaches the runner.\n\t\t\tif (target === undefined || !strict.is(target)) {\n\t\t\t\tthrow new WorkflowError('TOOL', 'malformed workflow definition', {\n\t\t\t\t\tworkflow: definition.id,\n\t\t\t\t})\n\t\t\t}\n\t\t\tif (depth + 1 > MAX_WORKFLOW_DEPTH) {\n\t\t\t\tthrow new WorkflowError(\n\t\t\t\t\t'DEPTH',\n\t\t\t\t\t`nested workflow exceeds max depth ${MAX_WORKFLOW_DEPTH}`,\n\t\t\t\t\t{\n\t\t\t\t\t\tworkflow: target.id,\n\t\t\t\t\t\tdepth,\n\t\t\t\t\t\tmax: MAX_WORKFLOW_DEPTH,\n\t\t\t\t\t},\n\t\t\t\t)\n\t\t\t}\n\t\t\tconst tag = workflowTag(target.id)\n\t\t\tif (ancestry.includes(tag)) {\n\t\t\t\tthrow new WorkflowError('DEPTH', `workflow '${target.id}' is already an ancestor (cycle)`, {\n\t\t\t\t\tworkflow: target.id,\n\t\t\t\t\tancestry: [...ancestry],\n\t\t\t\t})\n\t\t\t}\n\t\t\tconst result = await runner.execute(target, {\n\t\t\t\tdepth: depth + 1,\n\t\t\t\tancestry: [...ancestry, tag],\n\t\t\t})\n\t\t\treturn workflowToolSummary(result)\n\t\t},\n\t})\n}\n\n/**\n * Create the safe cross-environment cooperative-yield default — a\n * {@link SchedulerInterface} built on `setTimeout` / `clearTimeout` alone, so it\n * runs unchanged in both the browser and Node.\n *\n * @remarks\n * `yield()` gives the host a turn via a zero-delay macrotask (so pending I/O,\n * timers, and rendering actually run — a microtask would not); `delay(ms)` resumes\n * after at least `ms`. Pass `options.signal` to make a pending yield/delay reject\n * with the signal's `reason` on abort (with full timer/listener cleanup).\n * `options.priority` is accepted for contract compliance but treated uniformly by\n * this default — environment backends honour it.\n *\n * @returns A working {@link SchedulerInterface}\n *\n * @example\n * ```ts\n * import { createAbort, createScheduler } from '@src/core'\n *\n * const abort = createAbort()\n * const scheduler = createScheduler()\n *\n * // A cooperative loop: do a unit of work, then hand the host a turn.\n * while (!abort.signal.aborted) {\n * \tdoSomeWork()\n * \tawait scheduler.yield({ signal: abort.signal })\n * }\n * ```\n *\n * @example\n * ```ts\n * import { createScheduler } from '@src/core'\n *\n * // A backoff: wait a growing interval between retries.\n * const scheduler = createScheduler()\n * for (let attempt = 0; attempt < 5; attempt += 1) {\n * \tif (await tryOnce()) break\n * \tawait scheduler.delay(2 ** attempt * 100)\n * }\n * ```\n */\nexport function createScheduler(): SchedulerInterface {\n\treturn new Scheduler()\n}\n\n/**\n * Create a thin generic orchestrator that drives declared units — and any they\n * `spawn` — through a bounded-concurrency queue, collecting their results in order.\n *\n * @remarks\n * The Runner composes the workers `Queue` for backpressure, FIFO ordering, bounded\n * concurrency, retries, and the per-attempt timeout — it adds only orchestration, not\n * a second concurrency engine. `execute(inputs)` runs the unit set ONCE (a second call\n * throws) and resolves the units' results in order: the declared inputs first, then\n * any `spawn`ed siblings in spawn order. Each unit's handler gets a `Controller` — its\n * `id` / `input`, a `signal` that fires on the unit's `abort`, a runner-level `abort`,\n * or the attempt's timeout, a promise-parked `wait()`, and `spawn(input)` to fan out\n * sibling units. The run is **fail-fast**: the first unit failure (after retries)\n * aborts every other unit and rejects `execute` with that error. **Observable (§13):** a\n * typed `emitter` surfaces `start` / `unit` / `spawn` / `settle` / `fail` / `finish` / `abort`.\n *\n * Because `spawn` is fire-and-track (the runner awaits the whole spawn closure via an\n * outstanding-unit count, not a one-time snapshot), a handler need NOT await its spawns\n * for them to run — and on a bounded runner it should NOT `await` a spawn inline (a\n * slot-holding handler awaiting its own spawn can deadlock); fan out and return instead.\n *\n * @typeParam TInput - The work input each unit carries\n * @typeParam TResult - The value a unit's handler resolves\n * @param options - The `handler` plus optional `concurrency` (default `1`), `retries`\n * (default `0`), and a default per-attempt `timeout` in milliseconds\n * @returns A working {@link RunnerInterface}\n *\n * @example\n * ```ts\n * import { createRunner } from '@src/core'\n *\n * // A handler that fans out one sibling per declared unit, then returns its own value.\n * const runner = createRunner<number, number>({\n * \tconcurrency: 4,\n * \thandler: (controller) => {\n * \t\tif (controller.input < 10) controller.spawn(controller.input + 100) // fire-and-track\n * \t\treturn controller.input\n * \t},\n * })\n *\n * const results = await runner.execute([1, 2, 3])\n * // [1, 2, 3, 101, 102, 103] — declared inputs first (in order), then spawns (in order)\n * ```\n */\nexport function createRunner<TInput, TResult>(\n\toptions: RunnerOptions<TInput, TResult>,\n): RunnerInterface<TInput, TResult> {\n\treturn new Runner(options)\n}\n"],"mappings":"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"}
|