Skip to content
10 min read · 2,087 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
effectiveToolMethodsThe effective, deduped set of artifact method descriptors reachable on a class, leaf-first up the static prototype chain.
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


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