Four entry points.
main()
Set initial values and request resources once.
tick()
Consume the input snapshot and update model state.
render()
Read state and emit drawing commands only.
on_code_swap()
Restore invariants after compatible state migration.
function on_code_swap(): void {
if (state.selected >= state.item_count) {
state.selected = 0;
}
return;
}Input becomes intent, then state.
Read a frame snapshot at the start of tick(). Turn it into intent, apply systems in a documented order, and let render project the committed model.
function tick(): i32 {
let move_x: i32 = 0;
if (is_key_down(Scancode.Left)) { move_x -= 1; }
if (is_key_down(Scancode.Right)) { move_x += 1; }
state.player_x += move_x * state.speed;
if (should_quit()) { return 1; }
return 0;
}Rendering observes state; it is not an authority that changes gameplay.
Candidate builds are all-or-nothing.
On the desktop JIT development target, stasis play makes the edit → save → hot-swap loop the center of iteration. It watches the current import graph, compiles each saved .stasis candidate in the background, and attempts publication at a safe point between ticks. Compatible running state is preserved, so a gameplay session can continue without a process restart.
The background compiler builds a candidate generation. Between ticks, the runtime checks lifecycle ABI, target compatibility, and global layout; it migrates only through the bounded plan, runs on_code_swap(), then publishes one host-entry table.
edit source ↓ background compile + semantic checks ↓ between ticks: validate → migrate → on_code_swap() ↓ publish complete generation // any failure: keep previous code and state
JIT for development, AOT for release.
Development uses an in-process Cranelift JIT so the runtime can compile changed code without a process restart. Release builds use Cranelift AOT. Both share the direct-call lowering contract and lifecycle boundaries.
Development
Edit, save, and keep stasis play running: background candidates publish between ticks when compatible. The session keeps its compatible state and rejects unsafe candidates.
Release
Complete AOT finalization for a packaged program; no live-edit service required.
Packaging keeps this runtime contract while changing only the host shell. See the platform targets guide → for desktop archives, WebAssembly, Android, and iOS/iPadOS requirements.