{"version":3,"file":"templates.mjs","names":[],"sources":["../../../src/batteries/orchestration/templates.ts"],"sourcesContent":["/**\n * Template validation and instantiation for orchestration.\n *\n * @module @nhtio/adk/batteries/orchestration/templates\n *\n * @remarks\n * A template is a consumer-defined plan *shape* — written in TypeScript, registered with\n * `createOrchestration` at construction, and therefore versioned with the consuming application.\n * It needs no store seeding and can be **validated once at boot** rather than once per\n * instantiation, so a misconfigured deployment fails at startup with a named issue rather than at\n * the first use months later.\n *\n * Why templates exist at all is the small-model story: a small model working on a forty-node plan\n * does far better filling in five declared parameters than authoring forty nodes. The template is\n * the static part of that bargain — the consumer writes the shape, the model fills the holes.\n *\n * A template is **not** a plan. It has no lifecycle, no digest, no run, and cannot be approved.\n * Only its instantiations are plans, which is what keeps \"one plan id, at most one run\" intact\n * when the same template is instantiated fifty times: each instantiation is an independent plan\n * with its own id and digest.\n *\n * The two exported functions are the whole surface:\n *\n * - {@link validateTemplate} — runs at **construction**. Every issue it returns is decidable and\n *   total *because* a registered template is immutable: the graph cannot change after the check,\n *   so the answer cannot go stale. The most important check is the laundering rule (below).\n * - {@link instantiateTemplate} — validates the arguments a model offers against the declared\n *   `params`, mints a fresh plan, substitutes every hole, and appends the graph as authored ops.\n *\n * ## The laundering rule\n *\n * A `ParamRef` reaching a `call` node's `args` is refused unless a node on **every route** to that\n * call declares the corresponding field in `declassifies`. This is the taint story made static:\n * a substituted parameter value is like entry input — untrusted — and it may reach a `reason`\n * prompt but not a `call` node's args unless a node on every path to the call has declassified it.\n *\n * The check lives over the **template, not over an instantiation**, and that is the whole reason\n * it can be total: it runs at construction, once, over a graph that is immutable from that moment.\n *\n * **The narrower invariant, stated honestly:** *a template cannot launder its own parameters.* It\n * does **not** claim that a substituted value's template origin is tracked through arbitrary later\n * edits — nothing in a freely-mutable graph can track that. Once instantiated, the result is an\n * ordinary `editable` plan and a substituted value is an ordinary literal; a later `set_node_field`\n * routing that literal into a `call` arg is exactly as visible as in any hand-authored plan, which\n * is to say: it is in the operator's rendered prose, and the operator approves it. That is the\n * honest boundary, and it is the same one every hand-authored plan already has.\n */\n\nimport { ParamRef } from './encoding'\nimport { DEFAULT_PLAN_BOUNDS } from './types'\nimport { isInstanceOf, isObject } from '../../lib/utils/guards'\nimport type { PlanStore } from './store'\nimport type {\n  CallNodeDefinition,\n  DeclaredField,\n  EncodableValue,\n  InstantiateResult,\n  InvocableTools,\n  NodeId,\n  PlanBounds,\n  PlanEdge,\n  PlanIssue,\n  PlanNode,\n  PlanOp,\n  PlanTemplate,\n  TemplateDefinitionOf,\n  TemplateNode,\n} from './types'\n\n// ── local structural helpers ────────────────────────────────────────────────\n/**\n * True for a PLAIN object — one whose prototype is `Object.prototype` or `null`. This is the same\n * distinction the fold (`ops.ts`) and the encoder's key-sorting make: every encoder-owned value\n * (`Date`, `RegExp`, `Map`, `Set`, typed arrays, and the `NodeRef`/`ParamRef` instances) has a\n * non-plain prototype, so this is exactly the set whose keys substitution is allowed to walk.\n */\nconst isPlainObject = (v: unknown): v is Record<string, unknown> =>\n  isObject(v) &&\n  (Object.getPrototypeOf(v) === Object.prototype || Object.getPrototypeOf(v) === null)\n\n/** Every distinct simple path `fromId → … → toId` as node-id sequences; truncated at a hard cap. */\nconst simpleRoutesFrom = (\n  nodes: readonly TemplateNode[],\n  edges: readonly PlanEdge[],\n  fromId: NodeId,\n  toId: NodeId\n): NodeId[][] => {\n  const byFrom = new Map<NodeId, PlanEdge[]>()\n  for (const e of edges) {\n    const list = byFrom.get(e.from)\n    if (list) list.push(e)\n    else byFrom.set(e.from, [e])\n  }\n  const idSet = new Set(nodes.map((n) => n.id))\n  const routes: NodeId[][] = []\n  const dfs = (cur: NodeId, path: NodeId[]) => {\n    if (routes.length === MAX_ROUTES) return\n    for (const e of byFrom.get(cur) ?? []) {\n      if (path.includes(e.to) || !idSet.has(e.to)) continue\n      const next = [...path, e.to]\n      if (e.to === toId) {\n        routes.push(next)\n        if (routes.length > MAX_ROUTES) return\n      } else {\n        dfs(e.to, next)\n      }\n    }\n  }\n  dfs(fromId, [fromId])\n  return routes\n}\n\n/** The cap on distinct simple routes `simpleRoutesFrom` enumerates before giving up. */\nconst MAX_ROUTES = 10_000\n\n/** The single `entry` node of a template, or `undefined` when there is none or more than one. */\nconst singleEntry = (nodes: readonly TemplateNode[]): TemplateNode | undefined => {\n  const entries = nodes.filter((n) => n.kind === 'entry')\n  return entries.length === 1 ? entries[0] : undefined\n}\n\n/**\n * True when the node with id `rid` is a `call` declaring `path` in `declassifies`. Only a `call`\n * node can declassify (the sanctioned sanitisation point); every other kind never clears taint.\n */\nconst nodeDeclassifies = (nodes: readonly TemplateNode[], rid: NodeId, path: string): boolean =>\n  nodes.some((n) => {\n    if (n.id !== rid || n.kind !== 'call') return false\n    const def = n.definition as TemplateDefinitionOf<CallNodeDefinition>\n    return Array.isArray(def.declassifies) && pathIsDeclared(def.declassifies as string[], path)\n  })\n\n/** The `DeclaredField` whose `path` equals `path`, or `undefined`. */\nconst declaredFieldByPath = (\n  params: readonly DeclaredField[],\n  path: string\n): DeclaredField | undefined => params.find((p) => p.path === path)\n\n/**\n * True when a literal path equals, extends, or is a prefix of a declared field path — the same\n * prefix semantics the freeze validator uses for `NodeRef.path`, applied here to `declassifies`\n * coverage.\n */\nconst pathIsDeclared = (declared: readonly string[], path: string): boolean =>\n  declared.some((p) => p === path || p.startsWith(path + '.') || path.startsWith(p + '.'))\n\n/** Recursively collect every `ParamRef` in a staged value, in first-encountered order. */\nconst collectParamRefs = (value: unknown, out: ParamRef[]): void => {\n  if (ParamRef.isParamRef(value)) {\n    out.push(value)\n    return\n  }\n  if (Array.isArray(value)) {\n    for (const v of value) collectParamRefs(v, out)\n    return\n  }\n  if (isInstanceOf(value, 'Map', Map)) {\n    for (const [k, v] of value) {\n      collectParamRefs(k, out)\n      collectParamRefs(v, out)\n    }\n    return\n  }\n  if (isInstanceOf(value, 'Set', Set)) {\n    for (const v of value) collectParamRefs(v, out)\n    return\n  }\n  if (isPlainObject(value)) {\n    for (const key of Object.keys(value)) collectParamRefs(value[key], out)\n  }\n}\n\n/**\n * Recursively replace every `ParamRef` with the corresponding argument value. Plain objects,\n * arrays, `Map`s and `Set`s are walked; every other encoder-owned value (`NodeRef`, `Date`,\n * `RegExp`, typed arrays, bigint, luxon values) rides through by reference untouched. After this,\n * no `ParamRef` remains, so a substituted definition is an ordinary value in the `ArgValue` domain.\n */\nconst substituteParamRefs = (value: unknown, args: Record<string, EncodableValue>): unknown => {\n  if (ParamRef.isParamRef(value)) return args[value.path]\n  if (Array.isArray(value)) return value.map((v) => substituteParamRefs(v, args))\n  if (isInstanceOf(value, 'Map', Map)) {\n    const out = new Map<unknown, unknown>()\n    for (const [k, v] of value) out.set(substituteParamRefs(k, args), substituteParamRefs(v, args))\n    return out\n  }\n  if (isInstanceOf(value, 'Set', Set)) {\n    return new Set([...value].map((v) => substituteParamRefs(v, args)))\n  }\n  if (isPlainObject(value)) {\n    const out: Record<string, unknown> = {}\n    for (const key of Object.keys(value)) out[key] = substituteParamRefs(value[key], args)\n    return out\n  }\n  return value\n}\n\n/**\n * Validate the `args` map against the template's declared `params`, naming the offending param and\n * what was expected. Returns `{ok: true, values}` with the concrete per-param values on success,\n * or `{ok: false, detail}` on the first failure.\n */\nconst checkArgs = (\n  params: readonly DeclaredField[],\n  args: Record<string, EncodableValue>\n): { ok: true; values: Record<string, EncodableValue> } | { ok: false; detail: string } => {\n  for (const field of params) {\n    const value = args[field.path]\n    if (value === undefined && !(field.path in args)) {\n      return {\n        ok: false,\n        detail: `Param \"${field.path}\" is required and was not supplied; expected ${describe(field)}.`,\n      }\n    }\n    if (!typeMatches(field, value)) {\n      return {\n        ok: false,\n        detail: `Param \"${field.path}\" has the wrong type: expected ${describe(field)}, got ${describeValue(value)}.`,\n      }\n    }\n  }\n  return { ok: true, values: args }\n}\n\n/** A human phrase for what a declared field expects. */\nconst describe = (field: DeclaredField): string => {\n  switch (field.type) {\n    case 'string':\n      return field.maxBytes !== undefined\n        ? `a string of at most ${field.maxBytes} bytes`\n        : 'a string'\n    case 'number':\n      return 'a finite number'\n    case 'boolean':\n      return 'a boolean'\n    case 'enum':\n      return `one of ${field.values.map((v) => JSON.stringify(v)).join(', ')}`\n  }\n}\n\n/** A short human phrase for an actual argument value, for error detail text. */\nconst describeValue = (value: unknown): string => {\n  if (typeof value === 'string')\n    return JSON.stringify(value.length > 40 ? value.slice(0, 40) + '…' : value)\n  if (value === null) return 'null'\n  return typeof value\n}\n\n/** Whether a raw value satisfies a declared field's type and enum membership. */\nconst typeMatches = (field: DeclaredField, value: EncodableValue | undefined): boolean => {\n  if (value === undefined) return false\n  switch (field.type) {\n    case 'string':\n      if (typeof value !== 'string') return false\n      if (field.maxBytes !== undefined && byteLength(value) > field.maxBytes) return false\n      return true\n    case 'number':\n      return typeof value === 'number' && Number.isFinite(value)\n    case 'boolean':\n      return typeof value === 'boolean'\n    case 'enum':\n      return typeof value === 'string' && field.values.includes(value)\n  }\n}\n\n/** UTF-8 byte length of a string — the unit `maxBytes` is expressed in. */\nconst byteLength = (s: string): number => {\n  let bytes = 0\n  for (let i = 0; i < s.length; i++) {\n    const code = s.charCodeAt(i)\n    if (code < 0x80) bytes += 1\n    else if (code < 0x800) bytes += 2\n    else if (code >= 0xd800 && code <= 0xdbff && i + 1 < s.length) {\n      const next = s.charCodeAt(i + 1)\n      if (next >= 0xdc00 && next <= 0xdfff) {\n        bytes += 4\n        i++\n      } else {\n        bytes += 3\n      }\n    } else {\n      bytes += 3\n    }\n  }\n  return bytes\n}\n\n// ── validateTemplate ─────────────────────────────────────────────────────────\n/**\n * Validate a template against the invocable allowlist, once, at construction.\n *\n * @remarks\n * Every issue returned here is a blocking refusal: a deployment whose template fails this check\n * should fail to boot, not fail at the first instantiation months later. This is the whole point\n * of validating over the immutable template rather than over each (mutable) instantiation.\n *\n * The checks:\n *\n * 1. **Undeclared holes.** A `ParamRef` whose `path` does not name a declared `params` entry is\n *    refused — a template cannot substitute a parameter it never declared.\n * 2. **Unknown tools.** A `call` node naming a tool absent from `invocable.has(tool)` is refused,\n *    and the message names what *is* available so the author can fix it.\n * 3. **The laundering check.** A `ParamRef` reaching a `call` node's `args` is refused unless a\n *    node on every route to that call declares the corresponding field in `declassifies`. See the\n *    module TSDoc for the honest, narrower invariant this enforces — *a template cannot launder\n *    its own parameters* — and why nothing more is claimed.\n *\n * The route enumeration is capped at {@link MAX_ROUTES} paths. A template with more distinct\n * simple paths than that cannot prove that *every* route declassifies, and is conservatively\n * refused rather than trusted on a partial count.\n *\n * @param tpl - The template to validate.\n * @param invocable - The tier-C allowlist a staged `call` may invoke.\n * @returns Every blocking issue the template raises; an empty array means it is safe to register.\n */\nexport function validateTemplate(tpl: PlanTemplate, invocable: InvocableTools): PlanIssue[] {\n  const issues: PlanIssue[] = []\n  const entry = singleEntry(tpl.nodes)\n\n  // 1. Undeclared holes: every ParamRef must name a declared params entry.\n  for (const node of tpl.nodes) {\n    if (node.kind !== 'call') continue\n    const def = node.definition as TemplateDefinitionOf<CallNodeDefinition>\n    const refs: ParamRef[] = []\n    collectParamRefs(def.args, refs)\n    for (const ref of refs) {\n      if (!declaredFieldByPath(tpl.params, ref.path)) {\n        issues.push({\n          code: 'unknown_param',\n          message:\n            `Template \"${tpl.id}\" places a template hole \"${ref.path}\" in call node ` +\n            `\"${node.id}\", but no declared param has that path; name a declared param or add one.`,\n          nodeId: node.id,\n          severity: 'blocking',\n        })\n      }\n    }\n  }\n\n  // 2. Unknown tools: a call may only name a tool the allowlist recognises.\n  for (const node of tpl.nodes) {\n    if (node.kind !== 'call') continue\n    const def = node.definition as TemplateDefinitionOf<CallNodeDefinition>\n    const tool = def.tool as string\n    if (!invocable.has(tool)) {\n      const available = invocable.names()\n      issues.push({\n        code: 'unknown_tool',\n        message:\n          `Call node \"${node.id}\" in template \"${tpl.id}\" names tool \"${tool}\", which is not on ` +\n          `the allowlist; use one of the available tools: ${available.join(', ')}.`,\n        nodeId: node.id,\n        severity: 'blocking',\n      })\n    }\n  }\n\n  // 3. The laundering check: a ParamRef in a call's args is refused unless a node on EVERY route\n  //    to that call declares the corresponding field in `declassifies`. This runs over the\n  //    immutable template, so the answer is decidable and cannot go stale.\n  if (entry !== undefined) {\n    for (const node of tpl.nodes) {\n      if (node.kind !== 'call') continue\n      const def = node.definition as TemplateDefinitionOf<CallNodeDefinition>\n      const refs: ParamRef[] = []\n      collectParamRefs(def.args, refs)\n      if (refs.length === 0) continue\n      // Per-param path, so the message can name the hole and the missing declassification.\n      const paths = refs.map((r) => r.path).filter((p, i, arr) => arr.indexOf(p) === i)\n      const routes = simpleRoutesFrom(tpl.nodes, tpl.edges, entry.id, node.id)\n      const truncated = routes.length > MAX_ROUTES\n      for (const path of paths) {\n        // An unreachable call has no routes to itself; that is an unreachable-node concern that\n        // belongs to the plan validator, not the laundering rule.\n        if (routes.length === 0) continue\n        const everyRouteDeclassifies =\n          !truncated &&\n          routes.every((route) =>\n            // Every node strictly before the call on this route (including ancestors) declaring the\n            // path in `declassifies`. The call's OWN `declassifies` declassifies its OUTPUT, never\n            // its input, so the call itself cannot declassify its own argument.\n            route.slice(0, -1).some((rid) => nodeDeclassifies(tpl.nodes, rid, path))\n          )\n        if (!everyRouteDeclassifies) {\n          issues.push({\n            code: 'param_not_declassified',\n            message:\n              `Template \"${tpl.id}\" routes template hole \"${path}\" into the args of call node ` +\n              `\"${node.id}\" through a route that does not declassify it; every route to that call ` +\n              `must pass a node declaring \"${path}\" in \"declassifies\".${truncated ? ' The route count exceeds the enumeration cap, so safety cannot be proven.' : ''}`,\n            nodeId: node.id,\n            severity: 'blocking',\n          })\n        }\n      }\n    }\n  }\n\n  return issues\n}\n\n// ── instantiateTemplate ──────────────────────────────────────────────────────\n/**\n * Instantiate a template into a fresh, ordinary `editable` plan.\n *\n * @remarks\n * A template holds **op inputs without identity**: a `PlanOp` requires `opId`/`actorId`/`lamport`/\n * `at`, and no static literal can carry those — the same reason bounds are a fold seed rather than\n * an implied op. So instantiation **mints** that identity here, under the passed `actorId`, with a\n * monotonic lamport.\n *\n * The steps, in order:\n *\n * 1. **Validate `args` against `params`** — types (plus `maxBytes` on strings) and enum\n *    membership. On failure it returns `{ok: false, reason: 'invalid_args', detail}` naming the\n *    offending param and what was expected, rather than minting a broken plan.\n * 2. **`store.createPlan(planId, {provenance: {kind: 'template', template: tpl.id, args}})`** — the\n *    provenance is persisted by the store and returned by `readProvenance`, for the renderer and\n *    for audit. It is **not** a taint mechanism (see the module TSDoc).\n * 3. **Substitute every `ParamRef`** with the corresponding argument value, then append\n *    `add_node` / `add_edge` / `set_bounds` ops.\n *\n * The result is an **ordinary `editable` plan**: no inherited approval, no special state, nothing\n * downstream needs to know it came from a template. Two instantiations of one template yield\n * independent plans with different ids and digests.\n *\n * `planId` is minted (not a parameter), because a fresh plan needs a fresh id — a caller does not\n * pre-choose one. If the mint races a duplicate, an error is thrown rather than returning a broken\n * or mislabelled result.\n *\n * @param store - The plan store to write into.\n * @param tpl - The registered template to materialise.\n * @param args - The concrete values, keyed by declared param `path`, to substitute for holes.\n * @param actorId - The identity under which the minted ops are authored.\n * @returns The instantiation result.\n */\nexport async function instantiateTemplate(\n  store: PlanStore,\n  tpl: PlanTemplate,\n  args: Record<string, EncodableValue>,\n  actorId: string\n): Promise<InstantiateResult> {\n  const checked = checkArgs(tpl.params, args)\n  if (!checked.ok) {\n    return { ok: false, reason: 'invalid_args', detail: checked.detail }\n  }\n\n  const planId = `plan-${crypto.randomUUID()}`\n  const created = await store.createPlan(planId, {\n    provenance: { template: tpl.id, args: checked.values },\n  })\n  if (!created.ok) {\n    throw new Error(\n      `instantiateTemplate: store refused to create plan \"${planId}\" (${created.reason}); ` +\n        `a freshly-minted id collided or the store rejected the provenance.`\n    )\n  }\n\n  // Mint fresh identity under the passed actor, with a monotonic lamport. The fold orders ops by\n  // (lamport, actorId, opId), so each op needs a distinct opId even at the same lamport.\n  const at = new Date().toISOString()\n  const ops: PlanOp[] = []\n  let lamport = 1\n  const nextId = (): string => `${actorId}-${planId}-${lamport}-${crypto.randomUUID()}`\n\n  for (const node of tpl.nodes) {\n    ops.push({\n      op: 'add_node',\n      node: {\n        ...node,\n        definition: substituteParamRefs(node.definition, checked.values) as PlanNode['definition'],\n      } as PlanNode,\n      opId: nextId(),\n      actorId,\n      lamport,\n      at,\n    })\n    lamport++\n  }\n  const bounds: PlanBounds = tpl.bounds ?? DEFAULT_PLAN_BOUNDS\n  for (const edge of tpl.edges) {\n    ops.push({\n      op: 'add_edge',\n      edge,\n      opId: nextId(),\n      actorId,\n      lamport,\n      at,\n    })\n    lamport++\n  }\n  ops.push({\n    op: 'set_bounds',\n    bounds,\n    opId: nextId(),\n    actorId,\n    lamport,\n    at,\n  })\n  lamport++\n\n  const appended = await store.appendOps(planId, ops, 0)\n  if (!appended.ok) {\n    throw new Error(\n      `instantiateTemplate: store refused to append ops to \"${planId}\" (${appended.reason}).`\n    )\n  }\n\n  return { ok: true, planId, issues: [] }\n}\n"],"mappings":"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"}