Skip to content
2 min read · 312 words

Function: instantiateTemplate()

ts
function instantiateTemplate(
  store: PlanStore,
  tpl: PlanTemplate,
  args: Record<string, EncodableValue>,
  actorId: string,
): Promise<InstantiateResult>;

Defined in: src/batteries/orchestration/templates.ts:437

Instantiate a template into a fresh, ordinary editable plan.

Parameters

ParameterTypeDescription
storePlanStoreThe plan store to write into.
tplPlanTemplateThe registered template to materialise.
argsRecord<string, EncodableValue>The concrete values, keyed by declared param path, to substitute for holes.
actorIdstringThe identity under which the minted ops are authored.

Returns

Promise<InstantiateResult>

The instantiation result.

Remarks

A template holds op inputs without identity: a PlanOp requires opId/actorId/lamport/ at, and no static literal can carry those — the same reason bounds are a fold seed rather than an implied op. So instantiation mints that identity here, under the passed actorId, with a monotonic lamport.

The steps, in order:

  1. Validate args against params — types (plus maxBytes on strings) and enum membership. On failure it returns {ok: false, reason: 'invalid_args', detail} naming the offending param and what was expected, rather than minting a broken plan.
  2. store.createPlan(planId, {provenance: {kind: 'template', template: tpl.id, args}}) — the provenance is persisted by the store and returned by readProvenance, for the renderer and for audit. It is not a taint mechanism (see the module TSDoc).
  3. Substitute every ParamRef with the corresponding argument value, then append add_node / add_edge / set_bounds ops.

The result is an ordinary editable plan: no inherited approval, no special state, nothing downstream needs to know it came from a template. Two instantiations of one template yield independent plans with different ids and digests.

planId is minted (not a parameter), because a fresh plan needs a fresh id — a caller does not pre-choose one. If the mint races a duplicate, an error is thrown rather than returning a broken or mislabelled result.