@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:
- The encoder is required.
@nhtio/encoderis 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 eagerlyawait 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 andclaimRun— even an in-memory store needs them. - Encodables are registered once.
registerOrchestrationEncodables()is called here, once, becauseregisterClassis a global registry and decoding an unregistered class throws. - 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. - Every registered template is validated.
validateTemplateruns 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
| Interface | Description |
|---|---|
| AllPredicate | A predicate that is satisfied only when EVERY member is satisfied. |
| AnyPredicate | A predicate that is satisfied when AT LEAST ONE member is satisfied. |
| NotPredicate | A predicate that is satisfied exactly when its single member is NOT satisfied. |
| PlanLock | A single execution lease on one plan. |
| PlanLockFactory | Creates and restores PlanLock instances for a deployment. |
| PlanStore | The 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. |
| PredicateLeaf | A leaf predicate: read path from the readable context and compare it with op. |
Type Aliases
| Type Alias | Description |
|---|---|
| AppendResult | The 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. |
| ClaimRunResult | The 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. |
| CreateResult | The 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. |
| ParsePredicateResult | The result of parseStructuredPredicate: either a validated predicate, or a model-addressed reason naming the fix. |
| PredicateOp | The closed set of comparison operators a structured predicate leaf may name. |
| StructuredPredicate | The structured predicate IR — the value a branch/select node's predicate field holds when the structured cell interprets it. |
| TransitionRequest | The 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. |
| TransitionResult | The 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
| Variable | Description |
|---|---|
| createOrchestration | THE 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_UNAVAILABLE | An orchestration cell is unavailable. |
| E_ORCH_ENCODER_REQUIRED | A required orchestration encoder is not configured. |
Functions
| Function | Description |
|---|---|
| effectiveToolMethods | The effective, deduped set of artifact method descriptors reachable on a class, leaf-first up the static prototype chain. |
| isAllPredicate | Type guard for AllPredicate. An all combinator is a plain object whose sole discriminator key all holds an array of structured predicates. |
| isAnyPredicate | Type guard for AnyPredicate. An any combinator is a plain object whose sole discriminator key any holds an array of structured predicates. |
| isNotPredicate | Type guard for NotPredicate. A not combinator is a plain object whose sole discriminator key not holds a single structured predicate. |
| isPredicateLeaf | Type 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. |
| isStructuredPredicate | Type 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. |
| loadOnce | Wraps a cell's load() so it is idempotent and converts a failed lazy await import() into E_ORCH_CELL_UNAVAILABLE. |
| parseStructuredPredicate | Validates 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