{"version":3,"file":"executor.cjs","names":[],"sources":["../../../src/batteries/orchestration/executor.ts"],"sourcesContent":["/**\n * @module @nhtio/adk/batteries/orchestration/executor\n *\n * The breadth-first executor that walks a plan graph to a terminal state and returns a\n * {@link RunProjection} derived entirely from the durable event log.\n *\n * Correctness rests on a strict commit protocol rather than on in-memory bookkeeping. Before a\n * node may be invoked its `node_entered` event is durably appended and awaited; once it settles,\n * `node_settled`, every `edge_taken`, and the fresh `frontier_snapshot` are committed together as\n * one atomic batch. A resume folds the same log, so the projection it produces can never disagree\n * with what a resumed run would observe — the projection is the log, not a shadow copy this\n * executor happens to keep.\n *\n * Concurrency is controlled by `PlanStore.claimRun`, which enforces that a plan has at most one\n * live run for a given digest. The optional lock factory is a weaker, best-effort guard; the\n * durable claim is the contract, and the executor claims before invoking any node.\n */\n\nimport { foldRun } from './runs'\nimport { foldOps, branchKey } from './ops'\nimport { NodeRef as NodeRefClass } from './encoding'\nimport { effectiveToolMethods } from './artifact_methods'\nimport { joinPromptParts, decodeOutputSchema } from './reason'\nimport { isInstanceOf, isObject, isError } from '../../lib/utils/guards'\nimport {\n  nodeById,\n  outgoing,\n  incoming,\n  entryNodes,\n  handleAppliesTo,\n  readPath,\n  immediateDominator,\n} from './plan'\nimport type { PlanStore } from './store'\nimport type {\n  RunOptions,\n  RunEvent,\n  RunProjection,\n  PendingFrame,\n  JoinState,\n  FrameRef,\n  PlanEdge,\n  PlanNodeKind,\n  EdgeHandle,\n  NodeOutput,\n  OutputItem,\n  OutputTable,\n  ArtifactTable,\n  BranchId,\n  NodeRef,\n  ArgValue,\n  EncodableValue,\n  NodeOutcome,\n  PredicateEvaluator,\n  PredicateVerdict,\n  CallInvokerFn,\n  ReasonerFn,\n  SpooledArtifactLike,\n  DeclaredField,\n  RawPlanView,\n  RouteSegment,\n} from './types'\n\n/**\n * Upper bound on total node settlements before the executor aborts. Deliberately reported as\n * BUDGET EXHAUSTION, never as a cycle — the two are distinct failures.\n */\nconst TOTAL_STEPS_BUDGET = 4096\n\n/** The entry route: no segments. Every route in the graph originates here. */\nconst ENTRY_BRANCH: BranchId = { segments: [] }\n\nconst now = (): string => new Date().toISOString()\n\n/** One work-queue item: a frame plus its branch-local value and artifact tables. */\ninterface RunFrame {\n  frame: FrameRef\n  outputs: OutputTable\n  artifacts: ArtifactTable\n  /** The verdict a `branch`/`select` node computed, for edge firing. */\n  verdict?: PredicateVerdict\n  /**\n   * For a `join` frame only: the merged frame its COMPLETING arrival produced.\n   *\n   * @remarks\n   * A join is a barrier, so an arrival that leaves it open settles nothing and fires nothing.\n   * This field is how that decision reaches the walk loop, which owns edge firing: `undefined`\n   * means the barrier is still open and this frame parks, while a value means it closed and\n   * carries the merged identity and unioned tables the successor must inherit.\n   */\n  merged?: { frame: FrameRef; outputs: OutputTable; artifacts: ArtifactTable }\n  /** Ancestor route for runtime cycle defence, excluding the frame's own node. */\n  ancestors: string[]\n}\n\n/** A fired edge and the successor frame it produced. */\ninterface FiredEdge {\n  to: RunFrame\n  edge: PlanEdge\n}\n\n/** The canonical table key for a node on a branch. Always built via `branchKey`. */\nconst tableKey = (nodeId: string, branchId: BranchId): string => `${nodeId}:${branchKey(branchId)}`\n\n/** Fully-resolved execution dependencies. */\ninterface ResolvedDeps {\n  invokeCall: CallInvokerFn\n  reason: ReasonerFn\n  evaluators: PredicateEvaluator[]\n}\n\n/** State threaded through the whole walk; deliberately not module-global. */\ninterface ExecutorContext {\n  store: PlanStore\n  planId: string\n  runId: string\n  plan: RawPlanView\n  deps: ResolvedDeps\n  options: RunOptions\n  entryId: string\n  /** Open join barriers, keyed by correlation key. */\n  joins: Map<string, JoinState>\n  steps: number\n}\n\n/**\n * Execute a plan against external input and return the projection folded from the durable event\n * log. External input is materialised as the entry frame's `node_settled` before any other node\n * runs, so it is addressable by `NodeRef` exactly like any other node output and is rebuilt from\n * events on resume.\n *\n * @remarks\n * **ORDER OF OPERATIONS, because it is observable and load-bearing.** Everything that can refuse\n * a request happens BEFORE `claimRun`: the plan is read and folded, the entry node is located,\n * and `RunOptions.input` is validated against its `DeclaredField[]`. Only then is the run claimed.\n *\n * That ordering is not an optimisation. `claimRun` is irreversible by design — a plan admits one\n * run EVER and the store exposes no release — so a check that ran after it would burn the plan's\n * only run on a request that never invoked a single tool, leaving it permanently\n * `run_already_claimed` with `clonePlan` the only recovery. A rejected request must cost the plan\n * nothing.\n *\n * So a caller can rely on this: **if this function throws on invalid input, the plan is still\n * runnable.** Fix the input and call again.\n *\n * The budget is the PLAN'S `bounds.maxSteps`, not a library constant — bounds are plan content,\n * digested and approved by the operator. Exhausting it settles the run `halted` with\n * `budget_exhausted{settled}`, never `process_death`: the executor knows why it stopped, and a\n * resume re-reports the same cause rather than looping, because the bound has not changed.\n *\n * @param store The plan store backing the run.\n * @param planId The id of the plan to execute.\n * @param options Per-run input and override dependencies.\n * @returns The {@link RunProjection} folded from the run's event log.\n * @throws If `RunOptions.input` violates the entry node's declared fields — before any claim.\n */\nexport async function executePlan(\n  store: PlanStore,\n  planId: string,\n  options: RunOptions\n): Promise<RunProjection> {\n  // 1. EVERYTHING THAT CAN REFUSE, BEFORE THE CLAIM.\n  //\n  // `claimRun` is irreversible by design — a plan admits one run, EVER, and there is no release\n  // API to undo it. So every check that can reject a request has to happen first, or a rejected\n  // request burns the plan's only run: a malformed `input` would leave the plan permanently\n  // `run_already_claimed`, unrunnable for a request that never invoked a single tool, with\n  // `clonePlan` the only recovery. Reading and validating first costs one extra `readOps` on the\n  // refusal path and nothing on the success path, since the fold is reused below.\n  const state = await store.readState(planId)\n  const ops = await store.readOps(planId)\n  const { view: plan } = foldOps(planId, ops)\n\n  const entries = entryNodes(plan)\n  const entryNode = entries[0]\n  if (!entryNode) throw new Error(`plan \"${planId}\" has no entry node`)\n  if (entryNode.kind !== 'entry') throw new Error(`plan \"${planId}\" entry node is malformed`)\n  const entryDef = entryNode.definition\n\n  // Validate external input before any side effect AND before the claim.\n  validateInput(options.input, entryDef.input)\n\n  // 2. CLAIM. The durable claim — not the optional lock — enforces one plan, one run, ever.\n  const claim = await store.claimRun(planId, state.digest, options.resumeRunId)\n  if (!claim.ok) {\n    // A non-ok claim aborts the run and surfaces the reason, never proceeds. Every failure —\n    // `not_executable`, `digest_mismatch`, `run_already_claimed`, `run_not_found`,\n    // `run_already_settled` — is a hard refusal. Returning a projection for an existing run\n    // would silently mask a `run_already_claimed` and let a second caller observe (or appear\n    // to drive) a run that the durable claim exists to keep singular.\n    throw new Error(`cannot run plan \"${planId}\": ${claim.reason}`)\n  }\n\n  const runId = claim.runId\n  const deps = resolveDeps(options)\n\n  const ctx: ExecutorContext = {\n    store,\n    planId,\n    runId,\n    plan,\n    deps,\n    options,\n    entryId: entryNode.id,\n    joins: new Map(),\n    steps: 0,\n  }\n\n  const already = claim.resumed ? await store.readRunEvents(planId, runId) : []\n\n  const entryKey = tableKey(entryNode.id, ENTRY_BRANCH)\n  const entryOutput: NodeOutput = {\n    items: [{ json: { ...options.input } }],\n    branchId: ENTRY_BRANCH,\n  }\n  const entryFrame: RunFrame = {\n    frame: {\n      nodeId: entryNode.id,\n      kind: 'entry',\n      branchId: ENTRY_BRANCH,\n      viaEdgeId: undefined,\n    },\n    outputs: new Map([[entryKey, entryOutput]]),\n    artifacts: new Map(),\n    ancestors: [],\n  }\n\n  // Seed the work queue: from the folded log on resume, from the entry frame on a fresh run.\n  const queue: RunFrame[] = []\n  const seenFrames = new Set<string>()\n  if (claim.resumed) {\n    const projection = foldRun(already)\n    for (const pf of projection.frontier.frames) {\n      queue.push({ frame: pf.frame, outputs: pf.outputs, artifacts: pf.artifacts, ancestors: [] })\n    }\n    for (const j of projection.frontier.joins) {\n      ctx.joins.set(j.correlationKey, j)\n    }\n    ctx.steps = Math.max(0, countSettled(already))\n    if (!frameSettled(already, entryFrame.frame)) {\n      queue.unshift(entryFrame)\n    }\n  } else {\n    // A fresh run begins with run_started — the fold's required first event.\n    await store.appendRunEvents(planId, runId, [\n      { kind: 'run_started', runId, digest: state.digest, at: now() },\n    ])\n    queue.push(entryFrame)\n  }\n\n  let aborted = false\n\n  while (queue.length > 0) {\n    if (options.signal?.aborted) {\n      await finish(ctx, { cause: { kind: 'turn_abort' }, outcome: 'aborted' })\n      aborted = true\n      break\n    }\n    const current = queue.shift()!\n    const key = frameIdentity(current.frame)\n    if (seenFrames.has(key)) continue\n    seenFrames.add(key)\n\n    // Budget exhaustion is reported as BUDGET EXHAUSTION, never as a cycle — freeze proves the\n    // graph acyclic, so a plan can exhaust a budget through legitimate fan-out.\n    //\n    // The bound is the PLAN'S OWN `maxSteps`, not a module constant: bounds are plan content, so\n    // they are digested and the operator approved them. `TOTAL_STEPS_BUDGET` remains the fallback\n    // for a view with no bounds at all.\n    const stepBudget = ctx.plan.bounds?.maxSteps ?? TOTAL_STEPS_BUDGET\n    if (ctx.steps >= stepBudget) {\n      // NOT `process_death`. The executor knows precisely why it stopped, and mislabelling it\n      // sends an operator hunting a crash that never happened — while `foldRun` is explicit that\n      // process death is never inferred, only recorded by whoever resumes.\n      await finish(ctx, {\n        cause: { kind: 'budget_exhausted', settled: ctx.steps },\n        outcome: 'halted',\n      })\n      aborted = true\n      break\n    }\n    ctx.steps++\n\n    // 3a. BEFORE invoking: append `node_entered` durably and await the write.\n    await store.appendRunEvents(planId, runId, [\n      { kind: 'node_entered', frame: current.frame, at: now() },\n    ])\n\n    try {\n      await executeNode(ctx, current)\n\n      // A `join` whose barrier is still OPEN parks: it contributed its tables to the barrier and\n      // produces no settlement, no edge and no successor. The arrival that closes the barrier\n      // settles the join once, under the MERGED identity, so the successor is enqueued exactly\n      // once however many routes converged.\n      if (current.frame.kind === 'join') {\n        if (!current.merged) {\n          // Record the contribution durably (the barrier rides in `frontier_snapshot`) without\n          // settling the frame — an unsettled entered frame is exactly \"in flight\", which is what\n          // a parked arrival is.\n          await appendJoinParked(ctx, queue)\n          continue\n        }\n        // Re-key this frame to the merged identity before settling, so the settlement, the\n        // outgoing edges and the successor's tables all speak the merged route.\n        current.frame = current.merged.frame\n        current.outputs = current.merged.outputs\n        current.artifacts = current.merged.artifacts\n      }\n\n      // 3b. AFTER settling: settle + every edge_taken + snapshot as ONE atomic batch.\n      const successors = fireSuccess(ctx, current)\n      const nextRunFrames: FiredEdge[] = []\n      for (const s of successors) {\n        // Runtime cycle defence in depth: re-entering a node already on THIS frame's path is a\n        // true cycle. A diamond fan-in is not, because its paths differ.\n        if (current.ancestors.includes(s.to.frame.nodeId)) {\n          throw new Error(`runtime cycle: re-entering node \"${s.to.frame.nodeId}\"`)\n        }\n        const withAncestors: RunFrame = {\n          ...s.to,\n          ancestors: [...current.ancestors, current.frame.nodeId],\n        }\n        nextRunFrames.push({ to: withAncestors, edge: s.edge })\n        queue.push(withAncestors)\n      }\n      const settledOutcome: NodeOutcome = { status: 'ok', output: currentOutput(current) }\n      await appendSettledBatch(ctx, current, settledOutcome, nextRunFrames, queue)\n    } catch (err) {\n      const error = isError(err)\n        ? { name: err.name, message: err.message }\n        : { name: 'Error', message: String(err) }\n      const errorEdge = outgoing(plan, current.frame.nodeId).filter((e) => e.handle === 'error')\n      if (errorEdge.length > 0) {\n        // A HANDLED failure: record it, traverse error edges, and the run may still complete.\n        const failedOutcome: NodeOutcome = { status: 'failed', handled: true, error }\n        const successors = errorEdge.map((edge) => deriveTarget(ctx, current, edge))\n        for (const s of successors) {\n          const withAncestors: RunFrame = {\n            ...s.to,\n            ancestors: [...current.ancestors, current.frame.nodeId],\n          }\n          queue.push(withAncestors)\n        }\n        await appendSettledBatch(ctx, current, failedOutcome, successors, queue)\n      } else {\n        // No error edge: unhandled halt.\n        const failedOutcome: NodeOutcome = { status: 'failed', handled: false, error }\n        await store.appendRunEvents(planId, runId, [\n          { kind: 'node_settled', frame: current.frame, outcome: failedOutcome, at: now() },\n        ])\n        await finish(ctx, {\n          cause: { kind: 'node_failed', nodeId: current.frame.nodeId, handled: false },\n          outcome: 'aborted',\n        })\n        aborted = true\n        break\n      }\n    }\n  }\n\n  if (!aborted) {\n    // A join no live frame can still satisfy halts rather than hangs.\n    const unsatisfiable = [...ctx.joins.values()].find((j) => j.arrivals.length < j.required)\n    if (unsatisfiable) {\n      await finish(ctx, {\n        cause: { kind: 'join_unsatisfiable', nodeId: unsatisfiable.nodeId },\n        outcome: 'halted',\n      })\n    } else {\n      await finish(ctx, { outcome: 'completed' })\n    }\n  }\n\n  return foldRun(await store.readRunEvents(planId, runId))\n}\n\n/** Append the terminal run events (`run_interrupted` when a cause is supplied, then `run_settled`). */\nasync function finish(\n  ctx: ExecutorContext,\n  r: { outcome: 'completed' | 'halted' | 'aborted'; cause?: InterruptionCauseType }\n): Promise<void> {\n  const events: RunEvent[] = []\n  if (r.cause !== undefined) {\n    events.push({ kind: 'run_interrupted', cause: r.cause, at: now() })\n  }\n  events.push({ kind: 'run_settled', outcome: r.outcome, at: now() })\n  await ctx.store.appendRunEvents(ctx.planId, ctx.runId, events)\n}\n\ntype InterruptionCauseType = NonNullable<Extract<RunEvent, { kind: 'run_interrupted' }>['cause']>\n\n/**\n * Append the `frontier_snapshot` for a join arrival that PARKED at an open barrier.\n *\n * @remarks\n * The arrival settles nothing — an entered-but-unsettled frame is exactly \"in flight\", which is\n * what a contributed-and-waiting arrival is. What must reach the log is the BARRIER, because the\n * contributing branch's outputs and artifacts were consumed into it and exist nowhere else in the\n * frontier; without this a resume from a half-satisfied join could not rebuild its successor's\n * dataflow context.\n *\n * @param ctx - The executor context holding the open barriers.\n * @param queue - The live work queue, for the frontier's pending frames.\n */\nasync function appendJoinParked(ctx: ExecutorContext, queue: RunFrame[]): Promise<void> {\n  const frames: PendingFrame[] = queue.map((f) => ({\n    frame: f.frame,\n    outputs: f.outputs,\n    artifacts: f.artifacts,\n  }))\n  await ctx.store.appendRunEvents(ctx.planId, ctx.runId, [\n    { kind: 'frontier_snapshot', frames, joins: [...ctx.joins.values()], at: now() },\n  ])\n}\n\n/** Append `node_settled` + every `edge_taken` + the new `frontier_snapshot` as one batch. */\nasync function appendSettledBatch(\n  ctx: ExecutorContext,\n  current: RunFrame,\n  outcome: NodeOutcome,\n  successors: FiredEdge[],\n  queue: RunFrame[]\n): Promise<void> {\n  const events: RunEvent[] = [{ kind: 'node_settled', frame: current.frame, outcome, at: now() }]\n  for (const s of successors) {\n    events.push({\n      kind: 'edge_taken',\n      edgeId: s.edge.id,\n      handle: s.edge.handle,\n      from: current.frame,\n      to: s.to.frame,\n      outputs: s.to.outputs,\n      artifacts: s.to.artifacts,\n      at: now(),\n    })\n  }\n  const frames: PendingFrame[] = queue.map((f) => ({\n    frame: f.frame,\n    outputs: f.outputs,\n    artifacts: f.artifacts,\n  }))\n  const joins: JoinState[] = [...ctx.joins.values()]\n  events.push({ kind: 'frontier_snapshot', frames, joins, at: now() })\n  await ctx.store.appendRunEvents(ctx.planId, ctx.runId, events)\n}\n\n/** Count node settlements present in an existing log (a resume's step budget start). */\nfunction countSettled(events: RunEvent[]): number {\n  let n = 0\n  for (const e of events) if (e.kind === 'node_settled') n++\n  return n\n}\n\n/** Whether the log already contains a settlement for the given frame. */\nfunction frameSettled(events: RunEvent[], frame: FrameRef): boolean {\n  const key = frameIdentity(frame)\n  return events.some((e) => e.kind === 'node_settled' && frameIdentity(e.frame) === key)\n}\n\n/** Stable identity of a frame across the walk (node + route). */\nfunction frameIdentity(frame: FrameRef): string {\n  return tableKey(frame.nodeId, frame.branchId)\n}\n\n/** The settled `NodeOutput` a frame carries after a successful execution. */\nfunction currentOutput(current: RunFrame): NodeOutput {\n  return (\n    current.outputs.get(tableKey(current.frame.nodeId, current.frame.branchId)) ?? {\n      items: [],\n      branchId: current.frame.branchId,\n    }\n  )\n}\n\n/** Resolve per-run deps, supplying a safe default for anything missing. */\nfunction resolveDeps(options: RunOptions): ResolvedDeps {\n  const invokeCall: CallInvokerFn =\n    options.invokeCall ?? (() => Promise.reject(new Error('no invokeCall provided')))\n  const reason: ReasonerFn =\n    options.reason ?? (() => Promise.reject(new Error('no reason provided')))\n  return { invokeCall, reason, evaluators: options.evaluators ?? [] }\n}\n\n/** Validate external input against the entry node's declared fields. */\nfunction validateInput(\n  input: Record<string, EncodableValue>,\n  fields: readonly DeclaredField[]\n): void {\n  for (const field of fields) {\n    if (!(field.path in input)) {\n      throw new Error(`input is missing required declared field \"${field.path}\" for the entry node`)\n    }\n  }\n}\n\n/** Look up the plan's evaluator cell by id. */\nfunction evaluatorById(deps: ResolvedDeps, id: string): PredicateEvaluator | undefined {\n  return deps.evaluators.find((e) => e.id === id)\n}\n\n/** Execute a single node according to its kind, mutating the frame's tables. */\nasync function executeNode(ctx: ExecutorContext, current: RunFrame): Promise<void> {\n  const node = nodeById(ctx.plan, current.frame.nodeId)\n  if (!node) throw new Error(`unknown node \"${current.frame.nodeId}\"`)\n  const def = node.definition\n\n  switch (current.frame.kind) {\n    case 'entry':\n      // External input is already materialised as the entry frame's output; nothing to run.\n      return\n    case 'call': {\n      const args: Record<string, EncodableValue> = {}\n      for (const [k, v] of Object.entries((def as CallDef).args)) {\n        args[k] = resolveArg(current, v) as EncodableValue\n      }\n      const result = await ctx.deps.invokeCall({\n        tool: (def as CallDef).tool,\n        args,\n        signal: ctx.options.signal,\n      })\n      settleCallResult(current, result, (def as CallDef).output)\n      return\n    }\n    case 'reason': {\n      const rdef = def as ReasonDef\n      const prompt = joinPromptParts(rdef.prompt as { text: string }[], (ref) => {\n        const v = resolveRef(current, ref)\n        return v === undefined ? undefined : (v as EncodableValue)\n      })\n      const captured = await ctx.deps.reason({\n        prompt: String(prompt),\n        outputSchema: decodeOutputSchema(rdef.outputSchema),\n        maxAttempts: rdef.maxAttempts,\n        signal: ctx.options.signal,\n      })\n      setOutput(current, { items: [{ json: captured }] })\n      return\n    }\n    case 'transform': {\n      const tdef = def as TransformDef\n      const sourceArtifact = resolveArtifact(current, tdef.source)\n      if (!sourceArtifact) {\n        throw new Error(`transform source \"${tdef.source.node}\" has no artifact in this branch`)\n      }\n      const methods = effectiveToolMethods(sourceArtifact.constructor)\n      let value: unknown = sourceArtifact\n      for (const step of tdef.steps) {\n        const desc = methods.find((m) => m.name === step.name)\n        if (!desc) throw new Error(`unknown transform step \"${step.name}\" for artifact`)\n        const method = (value as Record<string, unknown>)[desc.method]\n        if (typeof method !== 'function') {\n          throw new Error(`artifact method \"${desc.method}\" is missing`)\n        }\n        value = await (method as (...a: unknown[]) => unknown).apply(\n          value,\n          step.args ? Object.values(step.args) : []\n        )\n      }\n      const items: OutputItem[] = []\n      if (tdef.emit.as === 'rows') {\n        if (!Array.isArray(value)) throw new Error(`transform emit 'rows' requires an array result`)\n        for (const row of value) {\n          items.push({\n            json: isObject(row)\n              ? (row as Record<string, EncodableValue>)\n              : { value: row as EncodableValue },\n          })\n        }\n      } else {\n        const out = typeof value === 'string' ? value : defaultSerialise(value)\n        items.push({ json: { [tdef.emit.field]: out } })\n      }\n      setOutput(current, { items })\n      return\n    }\n    case 'branch':\n    case 'select': {\n      const sdef = def as BranchDef | SelectDef\n      const cell = evaluatorById(ctx.deps, sdef.evaluator)\n      if (!cell) throw new Error(`no evaluator cell \"${sdef.evaluator}\" is registered`)\n      const verdict = await cell.evaluate(node, {\n        outputs: current.outputs,\n        frame: current.frame,\n      })\n      current.verdict = verdict\n      return\n    }\n    case 'join':\n      joinBarrier(ctx, current)\n      return\n  }\n}\n\ninterface CallDef {\n  tool: string\n  args: Record<string, ArgValue>\n  output: DeclaredField[]\n}\ninterface ReasonDef {\n  prompt: ({ text: string } | NodeRef)[]\n  outputSchema: string\n  maxAttempts: number\n}\ninterface TransformDef {\n  source: NodeRef\n  steps: { name: string; args?: Record<string, EncodableValue> }[]\n  emit: { as: 'value'; field: string } | { as: 'rows' }\n}\ninterface BranchDef {\n  evaluator: string\n}\ninterface SelectDef {\n  evaluator: string\n}\n\n/** Write a frame's branch-local output under its canonical key. */\nfunction setOutput(\n  current: RunFrame,\n  item: { items?: OutputItem[]; json?: Record<string, EncodableValue> }\n): void {\n  const key = tableKey(current.frame.nodeId, current.frame.branchId)\n  const items =\n    item.items ?? (item.json !== undefined ? [{ json: item.json }] : ([] as OutputItem[]))\n  const outputs = new Map<string, NodeOutput>(current.outputs)\n  outputs.set(key, { items, branchId: current.frame.branchId })\n  current.outputs = outputs\n}\n\n/** Store a call's result respecting the ToolResult narrowing rules. */\nfunction settleCallResult(\n  current: RunFrame,\n  result: unknown,\n  fields: readonly DeclaredField[]\n): void {\n  const key = tableKey(current.frame.nodeId, current.frame.branchId)\n  if (typeof result === 'string') {\n    const field = fields[0]?.path ?? 'value'\n    const outputs = new Map<string, NodeOutput>(current.outputs)\n    outputs.set(key, {\n      items: [{ json: { [field]: result } }],\n      branchId: current.frame.branchId,\n    })\n    current.outputs = outputs\n    return\n  }\n  // A SpooledArtifactLike goes into the ArtifactTable under the same key AND settles with\n  // whatever its declared `output` describes. Bytes/media were refused at freeze here.\n  const instance = instanceOfArtifact(result)\n  if (instance) {\n    const artifacts = new Map<string, SpooledArtifactLike>(current.artifacts)\n    artifacts.set(key, instance)\n    current.artifacts = artifacts\n    const json: Record<string, EncodableValue> = {}\n    for (const f of fields) {\n      const v = readPath(instance, f.path)\n      json[f.path] = (v !== undefined ? v : defaultSerialise(instance)) as EncodableValue\n    }\n    const outputs = new Map<string, NodeOutput>(current.outputs)\n    outputs.set(key, { items: [{ json }], branchId: current.frame.branchId })\n    current.outputs = outputs\n    return\n  }\n  throw new Error(`node \"${current.frame.nodeId}\" returned an unsupported result shape`)\n}\n\n/** Structural `SpooledArtifactLike` guard. */\nfunction instanceOfArtifact(v: unknown): SpooledArtifactLike | undefined {\n  if (isInstanceOf<SpooledArtifactLike>(v, 'SpooledArtifactLike')) return v\n  if (isObject(v) && typeof v.constructor === 'function') {\n    return v as SpooledArtifactLike\n  }\n  return undefined\n}\n\n/**\n * Resolve a `NodeRef` against the frame's branch-local `ArtifactTable`.\n *\n * @remarks\n * This mirrors {@link resolveRef}'s lookup EXACTLY, and must: the two tables are keyed\n * identically (`${nodeId}:${branchKey(branchId)}`) and `NodeRef.branchId` means the same thing\n * for both — WHICH EXECUTION of the node to read. An omitted `branchId` means \"do not filter\",\n * which is legal precisely when one path reaches the node, and freeze refuses it when more than\n * one does. So the omitted case must scan by node id rather than assume a route.\n *\n * Assuming the ENTRY route instead is wrong for every node except the entry node itself: a `call`\n * one edge in already carries `{segments:[{edge:'e0'}]}`, so its artifact is stored under that\n * key and an entry-keyed lookup misses it. That was a real defect — a linear\n * `entry → call → transform` plan froze clean and then failed at run time with \"no artifact in\n * this branch\", which is why the lookup lives in one function shared with the value path.\n *\n * @param frame - The live frame whose branch-local table is being read.\n * @param ref - The reference naming the producing node, and optionally which execution of it.\n * @returns The artifact instance, or `undefined` when the frame's table holds none for it.\n */\nfunction resolveArtifact(frame: RunFrame, ref: NodeRef): SpooledArtifactLike | undefined {\n  if (ref.branchId) return frame.artifacts.get(tableKey(ref.node, ref.branchId))\n  for (const [k, artifact] of frame.artifacts) {\n    if (k.startsWith(`${ref.node}:`)) return artifact\n  }\n  return undefined\n}\n\n/** Resolve a `NodeRef` against a frame's branch-local tables. */\nfunction resolveRef(frame: RunFrame, ref: NodeRef): unknown {\n  let output: NodeOutput | undefined\n  if (ref.branchId) {\n    output = frame.outputs.get(tableKey(ref.node, ref.branchId))\n  } else {\n    for (const [k, o] of frame.outputs) {\n      if (k.startsWith(`${ref.node}:`)) {\n        output = o\n        break\n      }\n    }\n  }\n  if (!output) return undefined\n  const items = output.items\n  let base: unknown\n  if (ref.select === 'first') base = items[0]?.json\n  else if (ref.select === 'last') base = items[items.length - 1]?.json\n  else if (ref.select === 'all') base = items.map((i) => i.json)\n  else base = items[ref.select.index as number]?.json\n  if (base === undefined) return undefined\n  return ref.path ? readPath(base, ref.path) : base\n}\n\n/** Resolve an `ArgValue` (which may contain `NodeRef`s) to a plain encodable. */\nfunction resolveArg(frame: RunFrame, value: ArgValue): unknown {\n  if (NodeRefClass.isNodeRef(value)) return resolveRef(frame, value)\n  if (Array.isArray(value)) return value.map((v) => resolveArg(frame, v as ArgValue))\n  if (isInstanceOf<SpooledArtifactLike>(value, 'SpooledArtifactLike')) return value\n  if (isObject(value)) {\n    const out: Record<string, unknown> = {}\n    for (const k of Object.keys(value)) {\n      out[k] = resolveArg(frame, value[k] as ArgValue)\n    }\n    return out\n  }\n  return value\n}\n\n/**\n * Barrier bookkeeping for a `join` node.\n *\n * @remarks\n * A join is a BARRIER, so the arrival that does not complete it must not settle the node: it\n * records itself and parks. Only the completing arrival produces a merged frame. `RunFrame.merged`\n * carries that decision back to the walk loop, which is where edge firing lives — a join whose\n * barrier is open fires nothing, and its successor is enqueued exactly once, by the arrival that\n * closed it.\n *\n * Late arrivals cannot occur, which is what makes this total: `required` is the join's in-degree,\n * and the diamond restriction makes that equal the number of fork→join routes, so the barrier\n * fires when every route has arrived and never before. There is no fired-barrier state to keep and\n * no second firing to guard against.\n *\n * A repeat of the same `(branchKey, edgeId)` pair is idempotent — a resumed run re-entering a\n * frame it already contributed must not count twice, or a two-route barrier would fire on one\n * branch arriving twice.\n *\n * @param ctx - The executor context holding the open barriers.\n * @param current - The arriving frame.\n */\nfunction joinBarrier(ctx: ExecutorContext, current: RunFrame): void {\n  const joinId = current.frame.nodeId\n  const fork = immediateDominator(ctx.plan, ctx.entryId, joinId) ?? ctx.entryId\n  const key = correlationKey(ctx, current.frame.branchId, joinId, fork)\n  const incomingEdges = incoming(ctx.plan, joinId)\n  const required = incomingEdges.length\n\n  const state: JoinState = ctx.joins.get(key) ?? {\n    nodeId: joinId,\n    correlationKey: key,\n    arrivals: [],\n    required,\n  }\n  const arrival: JoinState['arrivals'][number] = {\n    branch: current.frame.branchId,\n    edgeId: current.frame.viaEdgeId ?? '',\n    outputs: current.outputs,\n    artifacts: current.artifacts,\n  }\n  if (\n    !state.arrivals.some(\n      (a) => a.edgeId === arrival.edgeId && branchKey(a.branch) === branchKey(arrival.branch)\n    )\n  ) {\n    state.arrivals.push(arrival)\n  }\n  ctx.joins.set(key, state)\n\n  if (state.arrivals.length < state.required) {\n    // The barrier is still open. This frame contributes and parks: no output, no edges, no\n    // successor. It stays in `ctx.joins`, so a `frontier_snapshot` persists it and a resume\n    // restores it.\n    current.merged = undefined\n    return\n  }\n\n  ctx.joins.delete(key)\n\n  // ── the merged identity ────────────────────────────────────────────────────\n  // The correlation prefix is RETAINED and the join segment appended. A bare join segment is a\n  // graph constant, so two executions of one fork would render identically and collide; and the\n  // segment EXTENDS the route rather than replacing it, or two nodes reached by different\n  // post-join paths would collide in turn. `of` is the sorted list of ALL incoming edge ids — a\n  // graph constant, independent of which predicates fired, which is what makes a downstream\n  // `NodeRef` to a post-join node authorable at freeze.\n  const prefix = truncateAtFork(ctx, current.frame.branchId, fork)\n  const mergedBranch: BranchId = {\n    segments: [\n      ...prefix,\n      { join: joinId, of: incomingEdges.map((e) => e.id).sort((a, b) => (a < b ? -1 : 1)) },\n    ],\n  }\n\n  // ── the merged tables ──────────────────────────────────────────────────────\n  // The union of the arrivals' tables. Keys are `${nodeId}:${branchKey}`, path-unique, so the\n  // union cannot collide and needs no merge policy — which is what lets a downstream `NodeRef`\n  // resolve against an output produced on EITHER contributing branch.\n  const outputs = new Map<string, NodeOutput>()\n  const artifacts = new Map<string, SpooledArtifactLike>()\n  for (const a of state.arrivals) {\n    for (const [k, v] of a.outputs) outputs.set(k, v)\n    for (const [k, v] of a.artifacts) artifacts.set(k, v)\n  }\n\n  // ── the join's own output: provenance, and only provenance ─────────────────\n  // A join contributes no data of its own; it is a barrier. Its items say WHICH ROUTES converged,\n  // which is the only thing it actually knows, and is readable by a downstream predicate. The\n  // contributing nodes' real outputs are reached by referencing those nodes directly, which the\n  // unioned table above makes possible. Sorted by `via` then `branch` for a total order.\n  const items: OutputItem[] = state.arrivals\n    .map((a) => ({\n      json: {\n        via: a.edgeId,\n        from: sourceOfEdge(ctx, a.edgeId) ?? '',\n        branch: branchKey(a.branch),\n      } as Record<string, EncodableValue>,\n    }))\n    .sort((x, y) => {\n      const viaX = String(x.json.via)\n      const viaY = String(y.json.via)\n      if (viaX !== viaY) return viaX < viaY ? -1 : 1\n      return String(x.json.branch) < String(y.json.branch) ? -1 : 1\n    })\n\n  outputs.set(tableKey(joinId, mergedBranch), { items, branchId: mergedBranch })\n\n  current.merged = {\n    frame: {\n      nodeId: joinId,\n      kind: 'join',\n      branchId: mergedBranch,\n      viaEdgeId: current.frame.viaEdgeId,\n    },\n    outputs,\n    artifacts,\n  }\n}\n\n/** The source node of an edge id, for a join item's `from` provenance. */\nfunction sourceOfEdge(ctx: ExecutorContext, edgeId: string): string | undefined {\n  return ctx.plan.edges.find((e) => e.id === edgeId)?.from\n}\n\n/**\n * The arriving route truncated at the divergence fork — the barrier's shared prefix.\n *\n * @remarks\n * Every sibling route passes through the fork, so truncating there yields a prefix every arrival\n * to this join shares, while two executions of the fork reached by different outer routes keep\n * different prefixes and so keep separate barriers. The truncation point is the segment whose\n * edge ENTERS the fork; segments before and including it are kept.\n *\n * @param ctx - The executor context, for walking edges.\n * @param branch - The arriving route.\n * @param fork - The join's immediate dominator.\n * @returns The retained prefix segments.\n */\nfunction truncateAtFork(ctx: ExecutorContext, branch: BranchId, fork: string): RouteSegment[] {\n  const prefix: RouteSegment[] = []\n  let current = ctx.entryId\n  for (const seg of branch.segments) {\n    if (!('edge' in seg)) {\n      // An EARLIER join on this route. Keep the segment whole and advance the walk to that join\n      // node — the route continues from there, so failing to advance leaves `current` stale and\n      // the fork is never recognised, which splits what should be one barrier into two that can\n      // never close. (Found exactly that way: a diamond downstream of another diamond halted\n      // `join_unsatisfiable` with two barriers each holding one arrival.)\n      prefix.push(seg)\n      current = seg.join\n      if (current === fork) break\n      continue\n    }\n    prefix.push({ edge: seg.edge })\n    const edge = outgoing(ctx.plan, current).find((e) => e.id === seg.edge)\n    current = edge ? edge.to : current\n    if (current === fork) break\n  }\n  return prefix\n}\n\n/**\n * The arriving route truncated at the statically-known fork, rendered through the injective\n * `branchKey`, and namespaced by the join id.\n *\n * @param ctx - The executor context, for walking edges.\n * @param branch - The arriving route.\n * @param joinId - The join whose barrier is being keyed.\n * @param fork - The join's immediate dominator.\n * @returns The barrier's correlation key.\n */\nfunction correlationKey(\n  ctx: ExecutorContext,\n  branch: BranchId,\n  joinId: string,\n  fork: string\n): string {\n  return `${joinId}@${branchKey({ segments: truncateAtFork(ctx, branch, fork) })}`\n}\n\n/** Which success-path edges fire for a settled node. */\nfunction fireSuccess(ctx: ExecutorContext, current: RunFrame): FiredEdge[] {\n  const kind = current.frame.kind\n  const edges = outgoing(ctx.plan, current.frame.nodeId)\n  const result: FiredEdge[] = []\n  // `default` fires only when no match/case handled.\n  let anyMatchFired = false\n\n  for (const edge of edges) {\n    if (edge.handle === 'error') continue\n    if (edge.handle === 'default') continue\n    const fires = firesOnSuccess(kind, edge.handle, current)\n    if (fires) {\n      anyMatchFired = true\n      result.push(deriveTarget(ctx, current, edge))\n    }\n  }\n  if (!anyMatchFired) {\n    for (const edge of edges) {\n      if (edge.handle === 'default') {\n        result.push(deriveTarget(ctx, current, edge))\n      }\n    }\n  }\n  return result\n}\n\n/** Whether a non-error, non-default handle fires for the given success verdict. */\nfunction firesOnSuccess(kind: PlanNodeKind, handle: EdgeHandle, current: RunFrame): boolean {\n  // entry/call/reason/transform/join: only a success-path `always` fires.\n  if (kind !== 'branch' && kind !== 'select') {\n    return handle === 'always' && handleAppliesTo(kind, handle)\n  }\n  const v = current.verdict\n  if (!v) return false\n  if (kind === 'branch') {\n    if (v.kind !== 'branch') return false\n    if (handle === 'match') return v.matched\n    if (handle === 'no_match') return !v.matched\n    return false\n  }\n  if (v.kind !== 'select') return false\n  if (handle.startsWith('case_')) return v.caseLabel === handle.slice('case_'.length)\n  return false\n}\n\n/** Derive the successor frame for a fired edge, cloning branch-local tables. */\nfunction deriveTarget(ctx: ExecutorContext, current: RunFrame, edge: PlanEdge): FiredEdge {\n  const targetNode = nodeById(ctx.plan, edge.to)\n  const branchId: BranchId = { segments: [...current.frame.branchId.segments, { edge: edge.id }] }\n  const to: RunFrame = {\n    frame: {\n      nodeId: edge.to,\n      kind: targetNode?.kind ?? 'call',\n      branchId,\n      viaEdgeId: edge.id,\n    },\n    outputs: new Map(current.outputs),\n    artifacts: new Map(current.artifacts),\n    verdict: undefined,\n    ancestors: [],\n  }\n  return { to, edge }\n}\n\n/** Serialise an unknown value for a `value`-emitting transform field. */\nfunction defaultSerialise(v: unknown): string {\n  if (typeof v === 'string') return v\n  if (v === undefined) return '(undefined)'\n  if (v === null) return 'null'\n  if (Array.isArray(v)) return v.length === 0 ? '(empty list)' : v.join('\\n')\n  if (typeof v === 'number' || typeof v === 'bigint' || typeof v === 'boolean') return String(v)\n  try {\n    return JSON.stringify(v, null, 2)\n  } catch {\n    return String(v)\n  }\n}\n"],"mappings":"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"}