Are you an LLM? Read llms.txt for a summary of the docs, or llms-full.txt for the full context.
Skip to content

Runtime

import { createRuntime } from '@enc-protocol/cvn'
 
const rt = createRuntime({
  initial: Model,
  runAction: (cell, perform, path, value?) => void,
  performNow: (cmd) => CmdResult,
  onWarning?: (message) => void,
})
MemberMeaning
getState()the current model
setState(patch)cell.commit(patch) + notify
replaceState(next)cell.replace(next) + notify
subscribe(fn)notified on every commit; returns unsubscribe
action(path, value?)run one action inside a dispatch
perform(cmd)record (inside a dispatch) or perform now (outside)
inDispatchwhether an action is running
declaration{ owned, delegated, hostCapabilities }

The runner is late-bound to the dispatcher — on purpose

runAction receives the dispatcher's perform. A runner built on any other perform — say the host's own — records nothing in this dispatcher: every Cmd is performed at once, the drain is empty, and performNow is a declared capability nobody exercises. This happened in the port CVN came from, and it was found only when a Cmd routed through that performNow changed nothing. The runtime binds it for you; if you build a runner by hand, the port gate asserts the binding.

runAction is synchronous

Cmds emitted before the action returns are drained after it. If your action awaits, Cmds emitted after the first await are outside the dispatch and are performed immediately — which is correct, and is why an action that needs ordering emits its Cmds first.