{"version":3,"file":"plan.cjs","names":[],"sources":["../../../src/batteries/orchestration/plan.ts"],"sourcesContent":["/**\n * The IR's runtime helpers: pure, graph-shaped predicates and guards.\n *\n * @module @nhtio/adk/batteries/orchestration/plan\n *\n * @remarks\n * This module is the shared vocabulary that WP 04's freeze validation and WP 07's executor both\n * call. It performs NO validation policy itself and throws nothing — it answers questions about a\n * graph. Every export is a pure function over `{nodes, edges}` (a `RawPlanView` or any structural\n * subset carrying those two arrays), so the same code path serves a full folded view and a\n * hand-built slice.\n *\n * The functions here are deliberately small and single-purpose. Policy — \"exactly one entry\",\n * \"the graph is acyclic\", \"every join is a diamond\" — lives in the freeze validator, which\n * composes these primitives; the executor composes them to decide what fires next. Neither\n * reimplements a graph walk.\n */\n\nimport type { PlanNode, PlanEdge, NodeId, EdgeHandle, PlanNodeKind, RawPlanView } from './types'\n\n// ── the structural view ─────────────────────────────────────────────────────\n/**\n * The minimal structural surface these helpers read. A `RawPlanView` satisfies it; so does any\n * `{nodes, edges}` subset. Accepting the subset keeps the helpers usable on slices and test\n * fixtures without forcing a full view.\n */\nexport interface PlanGraphView {\n  /** Every node in the graph being examined, in no significant order. */\n  nodes: readonly PlanNode[]\n  /** Every edge in the graph being examined, over all handles. */\n  edges: readonly PlanEdge[]\n}\n\n/** Normalise a `RawPlanView` or a structural subset to the minimal view. */\nconst asView = (view: RawPlanView | PlanGraphView): PlanGraphView => view\n\n// ── shape guards ─────────────────────────────────────────────────────────────\n/** The closed set of `PlanNodeKind` values a well-shaped node may carry. */\nconst NODE_KINDS: ReadonlySet<string> = new Set([\n  'entry',\n  'call',\n  'reason',\n  'transform',\n  'branch',\n  'select',\n  'join',\n])\n\n/**\n * True when `v` is a well-shaped `PlanNode`.\n *\n * @remarks\n * A shape guard, not a validator: it checks the closed union of `kind` values and the presence of\n * the `id`/`definition` fields, and does not descend into the definition (whose shape is the\n * freeze validator's job). `kind` must be one of the seven closed values; anything else is not a\n * plan node. `id` must be a string; `definition` must be a non-null object. Extra fields are\n * tolerated — a node may carry `phase`.\n *\n * @param v - The value to test.\n * @returns True when `v` is a `PlanNode`.\n */\nexport const isPlanNode = (v: unknown): v is PlanNode => {\n  if (v === null || typeof v !== 'object') return false\n  const n = v as Record<string, unknown>\n  return (\n    typeof n.id === 'string' &&\n    typeof n.kind === 'string' &&\n    NODE_KINDS.has(n.kind) &&\n    n.definition !== null &&\n    typeof n.definition === 'object'\n  )\n}\n\n/** The closed set of literal `EdgeHandle` values (excluding the `case_` prefix). */\nconst EDGE_HANDLES: ReadonlySet<string> = new Set([\n  'always',\n  'match',\n  'no_match',\n  'default',\n  'error',\n])\n\n/**\n * True when `v` is a well-shaped `PlanEdge`.\n *\n * @remarks\n * A shape guard, not a validator. `handle` must be one of the closed `EdgeHandle` values — the\n * five literal handles, or a `case_${string}` (the `case_` prefix is reserved for `select` cases,\n * so any string starting with `case_` is a legal handle). `id`, `from` and `to` must be strings.\n * Extra fields are tolerated.\n *\n * @param v - The value to test.\n * @returns True when `v` is a `PlanEdge`.\n */\nexport const isPlanEdge = (v: unknown): v is PlanEdge => {\n  if (v === null || typeof v !== 'object') return false\n  const e = v as Record<string, unknown>\n  return (\n    typeof e.id === 'string' &&\n    typeof e.from === 'string' &&\n    typeof e.to === 'string' &&\n    typeof e.handle === 'string' &&\n    (EDGE_HANDLES.has(e.handle) || e.handle.startsWith('case_'))\n  )\n}\n\n// ── lookup ───────────────────────────────────────────────────────────────────\n/**\n * Look up a node by id.\n *\n * @param view - The graph to search.\n * @param id - The node id to find.\n * @returns The node, or `undefined` when no node carries that id.\n */\nexport const nodeById = (view: RawPlanView | PlanGraphView, id: NodeId): PlanNode | undefined =>\n  asView(view).nodes.find((n) => n.id === id)\n\n/**\n * The edges leaving a node.\n *\n * @param view - The graph to search.\n * @param nodeId - The source node id.\n * @returns Every edge whose `from` is `nodeId`, in view order.\n */\nexport const outgoing = (view: RawPlanView | PlanGraphView, nodeId: NodeId): PlanEdge[] =>\n  asView(view).edges.filter((e) => e.from === nodeId)\n\n/**\n * The edges entering a node.\n *\n * @param view - The graph to search.\n * @param nodeId - The target node id.\n * @returns Every edge whose `to` is `nodeId`, in view order.\n */\nexport const incoming = (view: RawPlanView | PlanGraphView, nodeId: NodeId): PlanEdge[] =>\n  asView(view).edges.filter((e) => e.to === nodeId)\n\n// ── entry ────────────────────────────────────────────────────────────────────\n/**\n * Every node of kind `'entry'`.\n *\n * @remarks\n * Whether exactly one exists is WP 04's rule, not this function's. The executor calls this to\n * find what to materialise; the freeze validator calls it to enforce the exactly-one invariant.\n * Returning an array (rather than a single node) keeps this a pure question about the graph and\n * lets the caller decide what a count of zero or more than one means.\n *\n * @param view - The graph to search.\n * @returns Every node whose `kind` is `'entry'`, in view order.\n */\nexport const entryNodes = (view: RawPlanView | PlanGraphView): PlanNode[] =>\n  asView(view).nodes.filter((n) => n.kind === 'entry')\n\n// ── reachability ─────────────────────────────────────────────────────────────\n/**\n * The forward closure from a start node over ALL edge handles.\n *\n * @remarks\n * `error` and `default` edges are included: a node reachable only over an error edge is still\n * reachable, because the executor can still execute it. The closure is the set of nodes reachable\n * by following any outgoing edge transitively. The start node itself is included. A node with no\n * outgoing edges contributes nothing further.\n *\n * @param view - The graph to search.\n * @param startId - The node to start from.\n * @returns The set of node ids reachable from `startId`, including `startId` itself.\n */\nexport const reachableFrom = (view: RawPlanView | PlanGraphView, startId: NodeId): Set<NodeId> => {\n  const g = asView(view)\n  const byFrom = new Map<NodeId, PlanEdge[]>()\n  for (const e of g.edges) {\n    const list = byFrom.get(e.from)\n    if (list) list.push(e)\n    else byFrom.set(e.from, [e])\n  }\n  const seen = new Set<NodeId>([startId])\n  const stack: NodeId[] = [startId]\n  while (stack.length > 0) {\n    const cur = stack.pop()!\n    for (const e of byFrom.get(cur) ?? []) {\n      if (!seen.has(e.to)) {\n        seen.add(e.to)\n        stack.push(e.to)\n      }\n    }\n  }\n  return seen\n}\n\n// ── cycle detection ──────────────────────────────────────────────────────────\n/**\n * Find a cycle in the graph, over EVERY edge handle.\n *\n * @remarks\n * A topological sort over all edges — `error` and `default` included — because an error edge back\n * to an ancestor is still a cycle: it can still execute, so it can still loop. A diamond fan-in\n * (two distinct paths reaching one node) is NOT a cycle and is not reported. The function returns\n * the CLOSING edge — the edge whose `to` is already on the current path — so a caller can name it\n * in an issue. Returns `undefined` when the graph is acyclic.\n *\n * The algorithm is an iterative DFS with three node states (unvisited / on-stack / done). When a\n * back edge is found, the edge that closes the cycle is returned immediately.\n *\n * @param view - The graph to search.\n * @returns The closing edge of the first cycle found, or `undefined` when acyclic.\n */\nexport const findCycle = (\n  view: RawPlanView | PlanGraphView\n): { edgeId: string; from: NodeId; to: NodeId } | undefined => {\n  const g = asView(view)\n  const byFrom = new Map<NodeId, PlanEdge[]>()\n  for (const e of g.edges) {\n    const list = byFrom.get(e.from)\n    if (list) list.push(e)\n    else byFrom.set(e.from, [e])\n  }\n  const state = new Map<NodeId, 0 | 1 | 2>() // 0 unvisited, 1 on-stack, 2 done\n  const stack: { node: NodeId; next: number }[] = []\n\n  for (const n of g.nodes) {\n    if (state.get(n.id) === 2) continue\n    state.set(n.id, 1)\n    stack.push({ node: n.id, next: 0 })\n    while (stack.length > 0) {\n      const top = stack[stack.length - 1]\n      const edges = byFrom.get(top.node) ?? []\n      if (top.next < edges.length) {\n        const e = edges[top.next]\n        top.next++\n        const s = state.get(e.to)\n        if (s === 1) {\n          return { edgeId: e.id, from: e.from, to: e.to }\n        }\n        if (s === undefined) {\n          state.set(e.to, 1)\n          stack.push({ node: e.to, next: 0 })\n        }\n      } else {\n        state.set(top.node, 2)\n        stack.pop()\n      }\n    }\n  }\n  return undefined\n}\n\n// ── simple paths ─────────────────────────────────────────────────────────────\n/** The cap on distinct simple paths `routesBetween` will enumerate before giving up. */\nconst MAX_ROUTES = 10_000\n\n/**\n * All distinct simple paths from one node to another.\n *\n * @remarks\n * A simple path is a route that visits no node twice. This is used to derive a join's `required`\n * (the number of fork→join routes) and to validate the diamond topology. The result is a list of\n * node-id sequences, each starting at `fromId` and ending at `toId`.\n *\n * **Blowup guard.** The number of simple paths in a DAG can be exponential in the node count, so\n * this enumerates at most {@link MAX_ROUTES} paths and stops. A caller that needs an exact count\n * (a join's `required`) must treat a truncated result as \"too many to count\" and refuse the graph\n * rather than trust a partial count — the freeze validator does exactly that. The cap is a\n * documented safety valve, not a correctness knob.\n *\n * @param view - The graph to search.\n * @param fromId - The start node id.\n * @param toId - The target node id.\n * @returns Every distinct simple path from `fromId` to `toId`, truncated at {@link MAX_ROUTES}.\n */\nexport const routesBetween = (\n  view: RawPlanView | PlanGraphView,\n  fromId: NodeId,\n  toId: NodeId\n): NodeId[][] => {\n  const g = asView(view)\n  const byFrom = new Map<NodeId, PlanEdge[]>()\n  for (const e of g.edges) {\n    const list = byFrom.get(e.from)\n    if (list) list.push(e)\n    else byFrom.set(e.from, [e])\n  }\n  const results: NodeId[][] = []\n  const path: NodeId[] = [fromId]\n  const onPath = new Set<NodeId>([fromId])\n\n  const dfs = (cur: NodeId): void => {\n    if (results.length >= MAX_ROUTES) return\n    if (cur === toId) {\n      results.push([...path])\n      return\n    }\n    for (const e of byFrom.get(cur) ?? []) {\n      if (onPath.has(e.to)) continue\n      onPath.add(e.to)\n      path.push(e.to)\n      dfs(e.to)\n      path.pop()\n      onPath.delete(e.to)\n      if (results.length >= MAX_ROUTES) return\n    }\n  }\n\n  dfs(fromId)\n  return results\n}\n\n// ── immediate dominator ──────────────────────────────────────────────────────\n/**\n * The immediate dominator of a node, relative to an entry.\n *\n * @remarks\n * The standard iterative dominator algorithm (Cooper–Harvey–Kennedy). A node `d` dominates `n`\n * when every path from `entryId` to `n` passes through `d`; the immediate dominator is the unique\n * strict dominator closest to `n`. A join's FORK is its immediate dominator — which is what makes\n * diamond joins decidable: the fork is known statically, so correlation and `required` are\n * computable at freeze.\n *\n * Returns `undefined` when `nodeId` is the entry itself (a node does not dominate itself in the\n * immediate sense) or when `nodeId` is unreachable from `entryId` (no dominator exists).\n *\n * @param view - The graph to search.\n * @param entryId - The entry node id.\n * @param nodeId - The node whose immediate dominator to find.\n * @returns The immediate dominator's id, or `undefined` when none exists.\n */\nexport const immediateDominator = (\n  view: RawPlanView | PlanGraphView,\n  entryId: NodeId,\n  nodeId: NodeId\n): NodeId | undefined => {\n  const g = asView(view)\n  if (nodeId === entryId) return undefined\n\n  const byFrom = new Map<NodeId, PlanEdge[]>()\n  const byTo = new Map<NodeId, PlanEdge[]>()\n  for (const e of g.edges) {\n    const o = byFrom.get(e.from)\n    if (o) o.push(e)\n    else byFrom.set(e.from, [e])\n    const i = byTo.get(e.to)\n    if (i) i.push(e)\n    else byTo.set(e.to, [e])\n  }\n\n  // Reachable set from entry, over all handles.\n  const reachable = new Set<NodeId>([entryId])\n  const stack: NodeId[] = [entryId]\n  while (stack.length > 0) {\n    const cur = stack.pop()!\n    for (const e of byFrom.get(cur) ?? []) {\n      if (!reachable.has(e.to)) {\n        reachable.add(e.to)\n        stack.push(e.to)\n      }\n    }\n  }\n  if (!reachable.has(nodeId)) return undefined\n\n  const nodes = g.nodes.map((n) => n.id).filter((id) => reachable.has(id))\n  const idSet = new Set(nodes)\n  const preds = new Map<NodeId, NodeId[]>()\n  for (const id of nodes) {\n    const ps: NodeId[] = []\n    for (const e of byTo.get(id) ?? []) {\n      if (idSet.has(e.from)) ps.push(e.from)\n    }\n    preds.set(id, ps)\n  }\n\n  // Initialise: entry dominates itself; everything else is dominated by everything.\n  const dom = new Map<NodeId, Set<NodeId>>()\n  for (const id of nodes) dom.set(id, new Set(nodes))\n  dom.set(entryId, new Set([entryId]))\n\n  // Iterate to a fixpoint.\n  let changed = true\n  while (changed) {\n    changed = false\n    for (const id of nodes) {\n      if (id === entryId) continue\n      const ps = preds.get(id) ?? []\n      if (ps.length === 0) continue\n      let newDom: Set<NodeId> | undefined\n      for (const p of ps) {\n        const pdom = dom.get(p)!\n        newDom = newDom === undefined ? new Set(pdom) : intersect(newDom, pdom)\n      }\n      newDom!.add(id)\n      if (!setsEqual(newDom!, dom.get(id)!)) {\n        dom.set(id, newDom!)\n        changed = true\n      }\n    }\n  }\n\n  // Immediate dominator: the CLOSEST strict dominator of nodeId (its dominator set minus\n  // itself). Among the strict dominators, the immediate dominator is the one dominated by every\n  // other strict dominator — i.e. the one closest to nodeId. So prefer `d` when `d` is dominated\n  // BY the current candidate (`idom` dominates `d`), NOT when `d` dominates `idom` (that would\n  // walk toward the farthest strict dominator, always `entry`).\n  const nodeDom = dom.get(nodeId)!\n  let idom: NodeId | undefined\n  for (const d of nodeDom) {\n    if (d === nodeId) continue\n    if (idom === undefined) {\n      idom = d\n      continue\n    }\n    // `d` is a better candidate if it is dominated by the current idom (i.e. is closer to nodeId).\n    if (dom.get(d)!.has(idom)) idom = d\n  }\n  return idom\n}\n\n/** Intersection of two sets. */\nconst intersect = <T>(a: Set<T>, b: Set<T>): Set<T> => {\n  const out = new Set<T>()\n  for (const v of a) if (b.has(v)) out.add(v)\n  return out\n}\n\n/** Set equality. */\nconst setsEqual = <T>(a: Set<T>, b: Set<T>): boolean => {\n  if (a.size !== b.size) return false\n  for (const v of a) if (!b.has(v)) return false\n  return true\n}\n\n// ── handle applicability ──────────────────────────────────────────────────────\n/**\n * Whether an edge handle may be used on an edge leaving a node of a given kind.\n *\n * @remarks\n * The applicability table, exactly:\n * - `entry` → `'always'`\n * - `call` | `reason` | `transform` → `'always'` | `'error'`\n * - `branch` → `'match'` | `'no_match'` | `'default'` | `'error'`\n * - `select` → `case_${string}` | `'default'` | `'error'`\n * - `join` → `'always'` | `'error'`\n *\n * This is a pure question about the graph; the freeze validator enforces it as policy. The\n * executor uses it to decide which handles may fire for a settled node's outcome.\n *\n * @param kind - The source node's kind.\n * @param handle - The edge handle to test.\n * @returns True when the handle is legal for that node kind.\n */\nexport const handleAppliesTo = (kind: PlanNodeKind, handle: EdgeHandle): boolean => {\n  switch (kind) {\n    case 'entry':\n      return handle === 'always'\n    case 'call':\n    case 'reason':\n    case 'transform':\n      return handle === 'always' || handle === 'error'\n    case 'branch':\n      return (\n        handle === 'match' || handle === 'no_match' || handle === 'default' || handle === 'error'\n      )\n    case 'select':\n      return handle.startsWith('case_') || handle === 'default' || handle === 'error'\n    case 'join':\n      return handle === 'always' || handle === 'error'\n  }\n}\n\n// ── prototype-pollution-safe path read ────────────────────────────────────────\n/** Segments that would let a crafted path reach the prototype chain. */\nconst FORBIDDEN_SEGMENTS: ReadonlySet<string> = new Set(['__proto__', 'prototype', 'constructor'])\n\n/**\n * Read a dot-path from a value, with a per-segment prototype-pollution guard.\n *\n * @remarks\n * This is the prototype-pollution guard, so it is strict. Each path segment is checked against\n * `__proto__`, `prototype` and `constructor` BEFORE it is used as a key; any of those is refused\n * (returns `undefined`) rather than followed. This prevents a crafted path like\n * `a.__proto__.polluted` or `constructor.prototype.x` from reaching the prototype chain. A\n * missing path — a segment that is absent, or a non-object intermediate — returns `undefined`.\n *\n * The guard is per-segment, not just on the whole path, because a path is split on `.` and each\n * segment is a separate key access; a single check on the joined string would miss a segment\n * smuggled past an object boundary. Empty segments (from a leading/trailing dot or a double dot)\n * are treated as missing and return `undefined`.\n *\n * @param value - The value to read from.\n * @param path - A dot-separated path, e.g. `'a.b.c'`.\n * @returns The value at the path, or `undefined` when the path is missing or refused.\n */\nexport const readPath = (value: unknown, path: string): unknown => {\n  if (path === '') return value\n  let cur = value\n  for (const seg of path.split('.')) {\n    if (seg === '' || FORBIDDEN_SEGMENTS.has(seg)) return undefined\n    if (cur === null || typeof cur !== 'object') return undefined\n    cur = (cur as Record<string, unknown>)[seg]\n  }\n  return cur\n}\n\n// ── id validation ────────────────────────────────────────────────────────────\n/**\n * Whether a string is a valid node id.\n *\n * @remarks\n * A valid node id is snake_case: lowercase ASCII letters, digits and underscores, with no `/` and\n * no leading `.`. The `/` and leading-`.` rules are load-bearing: a path-shaped id gets copied by\n * small models as a citation, which cost a real 35–57 dispatch re-cite loop in this repo. Keeping\n * node ids out of path shape means a model cannot mistake one for a file path and re-cite it.\n *\n * @param id - The string to test.\n * @returns True when `id` is a valid node id.\n */\nexport const isValidNodeId = (id: string): boolean =>\n  /^[a-z0-9_]+$/.test(id) && !id.startsWith('.') && !id.includes('/')\n\n/**\n * Whether a string is a valid edge id.\n *\n * @remarks\n * An edge id must match `/^[A-Za-z0-9_-]{1,64}$/` — no delimiter, no colon, no parenthesis — so\n * `branchKey` cannot be forged. This is the same charset rule the freeze validator enforces; this\n * guard is the pure predicate it calls. The length cap (1–64) bounds the length-prefixed route\n * rendering.\n *\n * @param id - The string to test.\n * @returns True when `id` is a valid edge id.\n */\nexport const isValidEdgeId = (id: string): boolean => /^[A-Za-z0-9_-]{1,64}$/.test(id)\n"],"mappings":"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"}