import type { RunnerDeps, TaskSpec } from "../core/types.js"; /** * design/98 §1.2 / §C — is LLM self-orchestration ACTIVE for this task? `true` ONLY when the task opted in * AND the deployment provides BOTH a hard sandbox (`workflowScriptRunner.safeForUntrustedScripts`) AND a * governance baseline (`workflowGovernanceBaseline`). This is the SINGLE gate that drives BOTH the * orchestration-prompt injection (S8a) and the `run_workflow` tool mount (S8c) — kept in lockstep so the * prompt never claims a capability the task lacks (§6.3). FAIL-CLOSED: any missing piece ⇒ off. */ export declare function isSelfOrchestrationActive(spec: TaskSpec, deps: RunnerDeps): boolean; /** * design/98 §C — the DEPLOYMENT-level capability: does this deployment SUPPORT self-orchestration / workflows * AT ALL? `true` ⟺ it provides BOTH a hard sandbox (`workflowScriptRunner.safeForUntrustedScripts`) AND a * governance baseline (`workflowGovernanceBaseline`). This is the deps half of {@link isSelfOrchestrationActive} * with NO per-task `selfOrchestration` opt-in — the canonical predicate a control plane projects onto a * capability surface (e.g. service `GET /v1/capabilities`.`workflows`) so a shell can HONESTLY gate `/workflows` * + ultracode affordances: dark when `false` (the deployment can never run a workflow), available when `true`. * * SINGLE SOURCE so the surfaced capability can never drift from the gate that actually mounts `run_workflow` * (a shell that shows `/workflows` as available while the engine fail-closes the tool = the exact mismatch * design/98 §6.3 forbids). Per-principal/tier gating does NOT exist today — this is deployment-wide. */ export declare function workflowsCapability(deps: RunnerDeps): boolean; /** * design/98 §1.2 — the task OPTED IN (`selfOrchestration:true`) but the deployment did not meet the bar (a * hard sandbox + a governance baseline), so self-orchestration is FAIL-CLOSED. Returns a human-readable * reason for an operator warning, or `null` when not in this state (off, or fully active). The runner emits * ONE operator-visible warning so a misconfigured opt-in is never silent. */ export declare function selfOrchestrationFailClosedReason(spec: TaskSpec, deps: RunnerDeps): string | null; /** * design/98 §D.3/§E.1 — the `WorkflowScriptRunner` SEAM for running an LLM-AUTHORED workflow script * (S8 self-orchestration). A deployment provides the runner; **core does NOT ship a hard sandbox** (the * isolated-vm / separate-process implementation is a deployment concern or a separate * `@ai-only/workflow-sandbox` package). Core defines this contract + a TRUSTED-DEV vm runner * ({@link import("./dev-vm-script-runner.js").devWorkflowScriptRunner}, S8b) that is explicitly NOT a * security boundary, plus a conformance contract a hard runner must pass. * * 🔴 **Membrane = STRUCTURAL constraint, not a behavioral promise (codex v3/v4 BLOCKER).** The seam's * `run()` accepts ONLY {@link WorkflowPrimitives} — a flat, sterile record of bound callbacks + a budget * DATA snapshot. It does NOT accept a `WorkflowRunContext` (a host object whose prototype chain the script * could walk via `ctx.constructor.constructor("return process")()` to escape). The engine extracts the bound * functions FROM the context and constructs the primitives; the host context object structurally never * enters the runner — there is no prototype chain into the host reachable from the script. A hard runner * bridges each primitive as an isolated-vm `Reference`/`Callback` and copies `scriptArgs` via `ExternalCopy`. */ /** The `export const meta = {...}` a workflow script declares (a PURE literal — parsed by the meta-AST, * never `eval`'d; design/98 §2.4). Only `name`/`description` are required; the rest is observability. */ export interface WorkflowMeta { name: string; description: string; /** PARITY-SPOT-WORKFLOW B7 (CC card pretty.js:448042): `model` on a phase entry documents that phase's * model override — parsed + stored + displayed on the pre-registered run phase (no behavior yet). */ phases?: Array<{ title: string; detail?: string; model?: string; }>; whenToUse?: string; } /** * The FLAT, STERILE primitives a workflow script may call — bound functions + a budget DATA snapshot, and * NOTHING else from the host (design/98 §2.1). NO `ctx` object, NO host prototype chain. The HARD runner * bridges each function as an isolated-vm `Reference`/`Callback` (the script `await`s them, round-tripping * back to the main isolate where the real {@link import("./workflow.js").WorkflowRunContext} executes them). * * The `spec`/`opts`/stage/thunk shapes are `unknown` at this boundary on purpose: an LLM-authored `spec` is * UNTRUSTED input that the engine's `agent` primitive validates + governs (whitelist construction + * `tightenTaskSpec`, design/98 §2.5) BEFORE it ever reaches `runner.runTask`. The seam must not promise a * trusted `TaskSpec` here. */ export interface WorkflowPrimitives { /** Spawn one governed sub-agent. `spec` is an UNTRUSTED `WorkflowAgentSpec` (whitelist-constructed by the * engine, design/98 §2.5); `opts` carries `label`/`phase`/`schema`. Resolves to the task result. */ agent(spec: unknown, opts?: unknown): Promise; /** Run thunks concurrently (BARRIER); a thrown thunk resolves to `null`. */ parallel(thunks: unknown[]): Promise; /** Run each item through all stages independently (no barrier between stages). */ pipeline(items: unknown[], ...stages: unknown[]): Promise; /** Group work under a named phase (observability). */ phase(title: string, body: unknown): Promise; /** Emit a narrator log line. */ log(message: string): void; /** LIVE budget accessors, mirroring {@link import("./workflow.js").WorkflowBudget} (NOT a one-shot data * snapshot — a static snapshot would break the `while (budget.remaining() > N)` budget-scaled-depth loop * the orchestration guidance promotes). `total` is a stable number/null; `spent()`/`remaining()` are bound * functions the hard runner bridges (an isolated-vm `Reference`/`Callback`, like the other primitives) so * each call re-reads the current spend. */ budget: { total: number | null; spent(): number; remaining(): number; }; } /** * The seam a deployment implements to execute an LLM-authored workflow script. The engine calls `run()` with * the sterile {@link WorkflowPrimitives} + the script source + (copied) args; the runner compiles/executes * the script in its isolation domain and returns the script's value + parsed {@link WorkflowMeta}. */ export interface WorkflowScriptRunner { /** * Whether this runner can SAFELY execute UNTRUSTED (LLM-authored) scripts. `true` = a hard sandbox * (isolated-vm / separate process + container/seccomp). `false` = trusted-DEV authors only (the Node `vm` * runner — NOT a security boundary, see {@link import("./dev-vm-script-runner.js").devWorkflowScriptRunner}). * * 🔴 The S8 gate (design/98 §C / §1.2) mounts the `run_workflow` tool + injects the orchestration prompt * ONLY when this is `true`. `selfOrchestration:true` with no hard runner ⇒ FAIL-CLOSED (tool not mounted, * prompt not injected, operator warning). Core NEVER runs an LLM script in the dev `vm`. */ readonly safeForUntrustedScripts: boolean; run(input: { scriptSource: string; primitives: WorkflowPrimitives; scriptArgs: unknown; /** * A HOST `AbortSignal` for ABORT CONTROL (the workflow aborting cancels the script run). 🔐 The runner MUST * NOT expose this raw host object to the untrusted script — a host object's `.constructor.constructor` climbs * to the host `Function`/`process`. Use it to abort isolate execution; if you surface abort-awareness to the * script at all, wrap it isolate-side. {@link assertWorkflowSandboxConformance} supplies a host signal and * probes for this leak (CORE-1~9 audit MAJOR). */ signal?: AbortSignal; }): Promise<{ result: unknown; meta: WorkflowMeta; }>; } //# sourceMappingURL=workflow-script-runner.d.ts.map