Skip to content
10 min read · 2,070 words

@nhtio/adk/batteries/orchestration ​

The orchestration battery — plan lifecycle, execution, and the model-facing tool forge.

Remarks ​

This is the battery's BARREL and its single entry point: the assembly gate where the work-package pieces (validation, approval, the executor, templates, rendering, the raw views, the outline reader and the tool forge) are wired together. It is the one place a precondition can be enforced for every operation, which is why the encoder requirement and evaluator loading live here rather than scattered across the modules that happen to need them.

Why createOrchestration is async ​

Construction is the last moment a deployment can fail LOUDLY and EARLY. Four things are resolved here, before any plan is created, frozen or approved:

  1. The encoder is required. @nhtio/encoder is declared an OPTIONAL PEER of the whole package — peer metadata is package-wide, not subpath-scoped, so making it required would force it on every consumer including the many who never import orchestration. The requirement is enforced where it CAN be: at construction, by eagerly await import('@nhtio/encoder') and throwing E_ORCH_ENCODER_REQUIRED (naming the package and its install command) if it is absent. Failing here means no plan is ever created, frozen or approved in a deployment missing the encoder — the property that actually matters. It is genuinely required because the digest comes from a lossless canonical encoding, and digests are load-bearing in every lifecycle transition, approval binding and claimRun — even an in-memory store needs them.
  2. Encodables are registered once. registerOrchestrationEncodables() is called here, once, because registerClass is a global registry and decoding an unregistered class throws.
  3. Every configured evaluator cell is loaded. await load() runs on each cell supplied at construction, so a missing optional peer surfaces HERE rather than part-way through a freeze. A cell supplied per-run is loaded at that point, with the same named error.
  4. Every registered template is validated. validateTemplate runs on each template and a blocking issue throws, so a misconfigured deployment fails at boot with a named error rather than at first instantiation months later.

Dependency precedence ​

Resolved HERE and stated once so it cannot drift: per-run wins field by field over construction; anything absent from both is a named error if the plan needs it. evaluators MERGE BY CELL id — a per-run cell replaces the configured one with the same id, others survive — because a run legitimately swaps one cell while keeping the rest. Everything else replaces wholesale.

Environment neutrality ​

The barrel stays environment-neutral: there is no node:* anywhere in its module graph. The Lua cell (./cells/lua) imports node:worker_threads and is therefore NOT re-exported here — it is reachable only via its own deep subpath.

The conformance suite (./conformance) is excluded for the same reason in a different dimension: it imports vitest, which is an OPTIONAL peer dependency. A barrel re-export makes that import part of every consumer's module graph, so import '@nhtio/adk/batteries/orchestration' fails with ERR_MODULE_NOT_FOUND for anyone who has not installed a test runner — which is every production consumer. It is reachable only via its own deep subpath, from a test environment where vitest is present. This matches batteries/vector, whose conformance suite is likewise vitest-based and likewise subpath-only. (batteries/sandbox DOES re-export its suite from its barrel, and that is fine: it asserts through a local assert helper and imports no test framework at all. The rule is about the vitest import, not about conformance suites.)

The structured and jexl cells, the types, the exceptions, the store contract and the in-memory store, and the raw/render/outline functions are all re-exported.

How the deep subpaths are named ​

Every module carrying an @module tag becomes one published entry, and the entry key is its FULL path from src/ — batteries/orchestration/forge, not forge. The build derives the map by scanning for those tags (getEntries in bin/utils), and the emitted declaration sits at the matching path, so dist/batteries/orchestration/types.d.ts and dist/types.d.ts are different files reached by different specifiers.

Stated because the leaf basenames repeat and that looks alarming: this battery ships forge and types, and so do the root package and several other batteries — 25 modules end in /types today, four in /forge. None of them collide, because nothing is keyed on the basename. A module tagged here can never overwrite @nhtio/adk/forge.

Interfaces ​

InterfaceDescription
AllPredicateA predicate that is satisfied only when EVERY member is satisfied.
AnyPredicateA predicate that is satisfied when AT LEAST ONE member is satisfied.
NotPredicateA predicate that is satisfied exactly when its single member is NOT satisfied.
PlanLockA single execution lease on one plan.
PlanLockFactoryCreates and restores PlanLock instances for a deployment.
PlanStoreThe one contract for plans and runs — not a second store. Every method is async; nothing here is sync-or-async. A durable plan store is I/O by nature, the lifecycle transition is inherently a round-trip, and the cell seam is async too, so a uniform Promise surface is one less thing for eleven work packages to get inconsistently right.
PredicateLeafA leaf predicate: read path from the readable context and compare it with op.

Type Aliases ​

Type AliasDescription
AppendResultThe outcome of an appendOps call. On success it carries the new revision and digest; on failure it names whether the plan was not editable (frozen) or the log had moved past expectedRevision, and carries the actual state so a stale writer learns what happened.
ClaimRunResultThe outcome of a claimRun call. On success it carries the run id and whether this call resumed an existing run; on failure it names whether the plan was not executable, its digest had moved, a run was already claimed, the named run did not exist, or the named run was already settled — carrying the existing run id where one exists.
CreateResultThe outcome of minting a plan (createPlan / clonePlan). On success it carries the new plan's revision and digest; on failure it names which precondition was violated.
ParsePredicateResultThe result of parseStructuredPredicate: either a validated predicate, or a model-addressed reason naming the fix.
PredicateOpThe closed set of comparison operators a structured predicate leaf may name.
StructuredPredicateThe structured predicate IR — the value a branch/select node's predicate field holds when the structured cell interprets it.
TransitionRequestThe transition request, as a DISCRIMINATED UNION over the legal pairs — so an illegal target genuinely is a type error at the call site, rather than a claim the signature does not back. expected.state is fixed per variant (it is implied by from), and approval is required exactly where it is meaningful. A BYO store receiving a malformed request over a wire still answers illegal_transition at runtime; the type is the first line, not the only one.
TransitionResultThe outcome of a transition call. On success it carries the new revision; on failure it names whether the plan was not in the expected state, its digest had moved, or the request was not a legal pair — carrying the actual state/digest so a caller that lost can read what happened.

Variables ​

VariableDescription
createOrchestrationTHE battery's single entry point. Everything public is reached through the Orchestration object it returns, so it is the one place a precondition can be enforced for every operation.
E_ORCH_CELL_UNAVAILABLEAn orchestration cell is unavailable.
E_ORCH_ENCODER_REQUIREDA required orchestration encoder is not configured.

Functions ​

FunctionDescription
isAllPredicateType guard for AllPredicate. An all combinator is a plain object whose sole discriminator key all holds an array of structured predicates.
isAnyPredicateType guard for AnyPredicate. An any combinator is a plain object whose sole discriminator key any holds an array of structured predicates.
isNotPredicateType guard for NotPredicate. A not combinator is a plain object whose sole discriminator key not holds a single structured predicate.
isPredicateLeafType guard for PredicateLeaf. A leaf is a plain object carrying a string path and a string op; the op is narrowed to PredicateOp only when it is a member of the closed set.
isStructuredPredicateType guard for the whole StructuredPredicate union. A value is a structured predicate iff it is one of the four shapes. Because the combinator shapes are discriminated by their single key and a leaf by path/op, the four guards are mutually exclusive.
loadOnceWraps a cell's load() so it is idempotent and converts a failed lazy await import() into E_ORCH_CELL_UNAVAILABLE.
parseStructuredPredicateValidates an untrusted EncodableValue into the structured predicate IR.

References ​

ApprovalRecord ​

Re-exports ApprovalRecord


ArgValue ​

Re-exports ArgValue


ArtifactClassLike ​

Re-exports ArtifactClassLike


ArtifactMethodDescriptor ​

Re-exports ArtifactMethodDescriptor


ArtifactTable ​

Re-exports ArtifactTable


AuthorityClaim ​

Re-exports AuthorityClaim


AuthorityVerb ​

Re-exports AuthorityVerb


BranchId ​

Re-exports BranchId


branchKey ​

Re-exports branchKey


BranchNodeDefinition ​

Re-exports BranchNodeDefinition


CallInvokerFn ​

Re-exports CallInvokerFn


CallNodeDefinition ​

Re-exports CallNodeDefinition


ClonedFrom ​

Re-exports ClonedFrom


computeAuthoritySet ​

Re-exports computeAuthoritySet


createDispatchReasoner ​

Re-exports createDispatchReasoner


createJexlCell ​

Re-exports createJexlCell


CreateOrchestration ​

Re-exports CreateOrchestration


createStructuredCell ​

Re-exports createStructuredCell


DeclaredField ​

Re-exports DeclaredField


decodeOutputSchema ​

Re-exports decodeOutputSchema


EdgeHandle ​

Re-exports EdgeHandle


effectiveToolMethods ​

Re-exports effectiveToolMethods


EncodableValue ​

Re-exports EncodableValue


EntryNodeDefinition ​

Re-exports EntryNodeDefinition


entryNodes ​

Re-exports entryNodes


ExecutePlanFn ​

Re-exports ExecutePlanFn


findCycle ​

Re-exports findCycle


foldOps ​

Re-exports foldOps


foldRun ​

Re-exports foldRun


ForgeOrchestrationOptions ​

Re-exports ForgeOrchestrationOptions


ForgeOrchestrationRuntime ​

Re-exports ForgeOrchestrationRuntime


forgeOrchestrationTools ​

Re-exports forgeOrchestrationTools


FrameRef ​

Re-exports FrameRef


FreezeInputs ​

Re-exports FreezeInputs


handleAppliesTo ​

Re-exports handleAppliesTo


immediateDominator ​

Re-exports immediateDominator


incoming ​

Re-exports incoming


InMemoryPlanStore ​

Re-exports InMemoryPlanStore


InstantiatedFrom ​

Re-exports InstantiatedFrom


InstantiateResult ​

Re-exports InstantiateResult


instantiateTemplate ​

Re-exports instantiateTemplate


InterruptionCause ​

Re-exports InterruptionCause


InvocableTools ​

Re-exports InvocableTools


isPlanEdge ​

Re-exports isPlanEdge


isPlanNode ​

Re-exports isPlanNode


isValidEdgeId ​

Re-exports isValidEdgeId


isValidNodeId ​

Re-exports isValidNodeId


JexlCellOptions ​

Re-exports JexlCellOptions


JexlTransform ​

Re-exports JexlTransform


JoinNodeDefinition ​

Re-exports JoinNodeDefinition


joinPromptParts ​

Re-exports joinPromptParts


JoinState ​

Re-exports JoinState


MediaLike ​

Re-exports MediaLike


nodeById ​

Re-exports nodeById


NodeId ​

Re-exports NodeId


NodeOutcome ​

Re-exports NodeOutcome


NodeOutput ​

Re-exports NodeOutput


NodeRef ​

Re-exports NodeRef


Orchestration ​

Re-exports Orchestration


outgoing ​

Re-exports outgoing


OutputItem ​

Re-exports OutputItem


OutputTable ​

Re-exports OutputTable


ParamRef ​

Re-exports ParamRef


PendingFrame ​

Re-exports PendingFrame


PhaseEntry ​

Re-exports PhaseEntry


PlanBounds ​

Re-exports PlanBounds


PlanDiff ​

Re-exports PlanDiff


planDigest ​

Re-exports planDigest


PlanEdge ​

Re-exports PlanEdge


PlanId ​

Re-exports PlanId


PlanIssue ​

Re-exports PlanIssue


PlanNode ​

Re-exports PlanNode


PlanNodeKind ​

Re-exports PlanNodeKind


PlanOp ​

Re-exports PlanOp


planOutline ​

Re-exports planOutline


PlanOutline ​

Re-exports PlanOutline


PlanProvenance ​

Re-exports PlanProvenance


planRead ​

Re-exports planRead


PlanSlice ​

Re-exports PlanSlice


PlanState ​

Re-exports PlanState


PlanSummary ​

Re-exports PlanSummary


PlanTemplate ​

Re-exports PlanTemplate


PredicateContext ​

Re-exports PredicateContext


PredicateEvaluator ​

Re-exports PredicateEvaluator


PredicateVerdict ​

Re-exports PredicateVerdict


PromptPart ​

Re-exports PromptPart


rawDiff ​

Re-exports rawDiff


rawOps ​

Re-exports rawOps


rawPlan ​

Re-exports rawPlan


RawPlanView ​

Re-exports RawPlanView


reachableFrom ​

Re-exports reachableFrom


readPath ​

Re-exports readPath


ReasonerFn ​

Re-exports ReasonerFn


ReasonNodeDefinition ​

Re-exports ReasonNodeDefinition


registerOrchestrationEncodables ​

Re-exports registerOrchestrationEncodables


renderPlan ​

Re-exports renderPlan


RenderPlanOptions ​

Re-exports RenderPlanOptions


routesBetween ​

Re-exports routesBetween


RouteSegment ​

Re-exports RouteSegment


RunDeps ​

Re-exports RunDeps


RunEvent ​

Re-exports RunEvent


RunOptions ​

Re-exports RunOptions


RunProjection ​

Re-exports RunProjection


SelectNodeDefinition ​

Re-exports SelectNodeDefinition


SpooledArtifactLike ​

Re-exports SpooledArtifactLike


stripInstructionTags ​

Re-exports stripInstructionTags


TemplateArgValue ​

Re-exports TemplateArgValue


TemplateDefinitionOf ​

Re-exports TemplateDefinitionOf


TemplateNode ​

Re-exports TemplateNode


ToolResult ​

Re-exports ToolResult


TransformNodeDefinition ​

Re-exports TransformNodeDefinition


validateReasonerOutput ​

Re-exports validateReasonerOutput


validateTemplate ​

Re-exports validateTemplate


wrapInstruction ​

Re-exports wrapInstruction