CVN
CVN is the shape an application takes when its kernel cannot touch the world and its host cannot decide anything.
- The kernel holds a Model and an
updatethat is total and synchronous: every action returns a new model and a list of Cmds — data describing effects, never the effects themselves. - A host (node, web, native) performs Cmds through ports it declared, and hands the kernel the capabilities it cannot own: a clock, timers, storage, the network, randomness.
- A declaration on the runtime says what the kernel owns, what it still borrows, and what the host must provide. The port is done when the borrowed list is empty — and the gates make sure "done" was not written by hand.
action ──▶ kernel.update(model, msg) ──▶ [model', Cmd[]]
│
dispatcher records, then drains
│
host.performNow(cmd) ─▶ portsCVN was extracted from impl-super-mvp, where the whole application runtime was moved into this shape one borrowed method at a time, with every claim tied to code by a gate. What is in this package is what survived that: the dispatcher, the state cell, the runtime, one host contract with node and web behind it, a conformance suite every host runs, the gates, and cvn/enc — the ENC rules the port surfaced, each pinned by a Lean model whose cases the real code replays.
import { createRuntime, router, performed } from '@enc-protocol/cvn'
import { createNodeHost } from '@enc-protocol/cvn/node'
const host = createNodeHost()
const rt = createRuntime({
initial: { count: 0 },
runAction: (cell, perform, path) => {
if (path === '/inc') cell.commit({ count: cell.value.count + 1 })
if (path === '/save') perform({ kind: 'persist', key: 'count', value: cell.value.count })
},
performNow: router({
persist: (cmd) => (host.store.setJSON(cmd.key, cmd.value), performed()),
}),
})
rt.action('/inc')
rt.action('/save')Start with Concepts, then The rules. If you are implementing a host, go straight to Hosts and Native.