behavior-contracts
v0.8.0
Published
Language-agnostic runtime core for behavior contracts (dsl-contracts): validateEnvelope / evaluateExpression / renderTemplate / runPlan / canonical serialization. Single source of truth for the shared DSL runtime primitives.
Downloads
3,027
Maintainers
Readme
behavior-contracts
behavior-contracts is a library for declarative, statically-resolvable behavior/DSL
contracts. A contract is compiled to a portable, language-neutral IR and then either
compiled to genuinely-native per-language code (Go and Rust) that runs at
hand-written-SDK-floor parity, or interpreted by a small shared multi-language runtime
(TypeScript / Python / PHP / Rust / Go). The IR is deterministic and
canonically-serialized, so the same contract produces byte-identical output across every
consumer language.
Features
- Native typed-native codegen for Go and Rust. A covered contract is emitted as straight-line native code — direct struct field access, concrete per-node calls, and a local error type — running at SDK-floor parity (~0–5% overhead vs. a hand-written SDK baseline) and ~2–3× faster than the shared interpreter.
- Zero-runtime generated modules. The generated Go/Rust modules import no
behavior-contractsruntime at all — a property the compiler verifies (a build gate rejects any runtime reference or boxing primitive that leaks into the output). - Async or sync output, selectable. Pass
ioModel: "async"to emitasync fn/.awaitfor async-capable targets;"sync"is the default. - Fail-closed, never silently boxed. Shapes not yet natively coverable are rejected at generation time rather than falling back to a boxed/interpreted path labelled as native.
- Portable IR, consumed identically across languages. The same language-neutral IR runs through the shared interpreter in TypeScript, Python, PHP, Rust, and Go with identical semantics.
- Deterministic, canonical serialization. Key-sorted, typed-value encoding with a canonical decimal float representation — the same contract always serializes to the same bytes, which is what makes cross-language conformance verifiable.
Native codegen is Go and Rust only. TypeScript, Python, and PHP consume the portable IR through the shared interpreter.
Install
npm install behavior-contracts- ESM-only library; TypeScript type declarations are included.
- Requires Node.js 22+.
- No runtime dependencies.
Usage
A contract is authored as an IR (a portable component graph). You can either generate a native module from it, or interpret it directly with the shared runtime.
Generate a native module
import { generateModule } from "behavior-contracts";
// `ir` is a portable component-graph IR (language-neutral).
const mod = generateModule(ir, {
language: "go-typed-native", // or "rust-typed-native"
ioModel: "async", // "sync" (default) | "async"
});
console.log(mod.language); // "go"
console.log(mod.filenameHint); // e.g. "behaviors.generated.go"
console.log(mod.fingerprint); // IR fingerprint (build-time skew gate)
// mod.code is the full, runtime-free native source — write it to a file and compile it.generateModule also emits interpreted modules for other targets — pass
language: "typescript", "python", "php", "rust", or "go". It is fail-closed:
an unknown language, a non-portable IR, or a shape the target emitter cannot cover
natively throws rather than degrading silently.
Interpret the IR directly
import { runBehavior } from "behavior-contracts";
// Inject boundary handlers; the interpreter walks the portable IR.
const result = runBehavior(ir, handlers, { userId: "u1" }, "UserReads");Public primitives
The shared runtime also exposes the individual COMMON primitives piecewise:
| Export | Purpose |
|---|---|
| validateEnvelope | spec-version fail-closed validation (loud-rejects unknown versions) |
| evaluateExpression | evaluate the portable expression IR |
| renderTemplate | pure {param} string substitution |
| runPlan | execute the portable execution-plan IR |
| canonicalValue / canonicalJson | deterministic canonical serialization (sorted keys, compact JSON, canonical decimal floats) |
| runBehavior | execute the portable component-graph IR (handlers injected at the boundary) |
| generateModule | emit a native (Go/Rust typed-native) or interpreted module from the portable IR |
| assertPortable / assertPortableComponentGraph | Portability Guard (fail-closed structural validation of portable IR) |
| SemanticBehavior / behavior / compileBehaviors / catalogComponents / when + expression builders | effect-agnostic authoring surface — each public method of a marked class lowers to one component-graph root Behavior |
| referencedComponents / classifyBehaviorEffect | consumer-side CQRS derivation from the lowered graph |
Spec versions
This package tracks the IR/vector protocol versions independently from its library (semver) version:
| Spec | Version | |---|---| | expression | 2 | | template | 1 | | plan | 1 | | canonical | 2 | | behavior | 2 | | envelope | 1.1 |
License
MIT — see LICENSE.
