Runtime API & wire formats
The implemented contract between scene authors, Rust and platform adapters.
Rust entry points
| API | Contract |
|---|---|
compile(source) | Parses bounded UTF-8 Konjure DSL, validates it and returns a SceneDocument or Diagnostic |
validate(document) | Checks version, identifiers, units, topology and semantic resource limits |
tessellate(geometry) | Returns indexed positions and normals; group has no drawable mesh |
Runtime::new(document) | Validates and prepares immutable geometry plus mutable action state |
runtime.meshes() | Prepared meshes keyed by entity ID; upload them once |
runtime.sample(seconds) | Produces a frame for explicit time and current action state without advancing a hidden clock |
runtime.dispatch(event) | Applies one declared action atomically or returns an error |
Recording::validate() | Checks the version and bounds of an ordered decision recording |
sample can fail when composed transforms exceed renderable bounds even if all
local transforms are valid. Prepare a candidate and sample its initial frame
before replacing an accepted scene. An authored external mesh reference remains
unresolved in this preview and is explicitly rejected by runtime construction.
Coordinates and time
Positions and geometry lengths use metres. Scene coordinates are right-handed, with +Y up and -Z forward. Quaternions are unit length. Draw matrices contain 16 column-major values and preserve nonuniform parent composition, including shear. Adapters apply their host coordinate conversion exactly once.
Sample time is an explicit non-negative number of seconds. spin is rotation
about the local Y axis composed with authored rotation; orbit modifies local
X/Z translation, and bob modifies local Y translation. Toggling motion disables
these absolute-time offsets; it is not a paused animation clock. The playground’s
Play/Pause control pauses scene time instead.
Bounded inputs
DSL source is limited to 64 KiB and scenes to 256 entities with at most 16 levels of hierarchy. Each entity has at most 32 actions and 16 animation components. Identifiers use at most 128 ASCII letters, digits, underscores or hyphens and start with a letter or underscore. Conversation messages are UTF-8, with 16 KiB per message and at most 256 messages.
Primitive sizes and animation periods lie in the inclusive range 0.000001 to 1,000,000 in their respective units. Local and composed world transform values are bounded; collapsed or nearly singular world bases are rejected before an adapter can silently turn them into invalid float matrices. The runtime retains the latest 64 action events; durable recordings belong to the host.
Recordings allow at most 4096 steps and 256 events per step. CLI and binding JSON inputs also have byte limits. These limits are a preview profile, not a claim that every embedded board can fit the maximum scene.
Documents, events and receipts
.kj is authored text. Compiled .konjure JSON starts with
"format": "konjure.scene" and "version": 1. DTOs reject unknown fields;
format migration must be explicit. Public contracts are generated from Rust:
An action event has the following shape:
{"kind":"invoke_action","entity":"signal","action":"motion"}Receipts use applied for an internal state change and proposed for an external
effect request. Replay never executes tools or physical effects. Observation
timestamps and sequence numbers serialize as decimal strings so JavaScript does
not lose 64-bit integer precision. Observation metadata is an extension contract;
sensor payload ingestion and frame/clock reconciliation are host work.
WASM frame layout
SdkRuntime exposes document_json, meshes_json, ids_json, sample_json,
dispatch, and frame. Free the runtime when its host component is disposed.
frame(t) returns 20 floats per entity in the stable order returned by ids_json:
16 world-matrix values followed by red, green, blue and alpha in 0–1. Geometry
stays separate from this per-frame transfer. The browser adapter owns its camera,
materials, GPU resources and XR session; it does not reinterpret DSL behavior.