moxzi
Docs / Reference / Changelog

Changelogalpha

What changed, and what breaks?

moxzi is at 0.1.0-alpha.6. This page summarises each alpha and states the compatibility policy that governs what happens next, because an alpha whose stability rules are unwritten is one where every change is a surprise. The full, itemised record is CHANGELOG.md in the repository; the release notes quote the artifact hashes.

How versions work#

RuleDetail
One version for four productsthe CLI, the server, the browser package and the on-chain builder version together; one tag covers the release train (CHANGELOG.md)
SemVerwith the alpha caveat below
Artifacts carry hashescompiler.wasm and linker.wasm ship beside each release and their SHA-256s are quoted in the release notes, taken from dist/SHA256SUMS
The wasm is platform-neutralthe same compiler bytes for every target tarball; only the native binaries differ
Releases are gated, not hopedscripts/release.sh stages a tarball and then builds hello.mo from inside it with MOXZI_COMPILER and MOXZI_LINKER scrubbed. If the clean directory cannot build, there is no release

alpha-7 (unreleased)#

Three themes: Motoko actors on nine actor platforms, in the platform's own process, with the platform owning the actor's durable image; what one of those actors costs; and mops interop, including an Internet Computer agent written in Motoko. CHANGELOG.md under ## Next is the itemised record.

AreaWhat changed
Hostsone compiled actor passes the 16-scenario conformance matrix on Restate, Temporal, Dapr, Orleans, Akka (Pekko), Proto.Actor, Ray, wasmCloud and Cloudflare Durable Objects, each in process through moxzi-rts (linked, cgo, P/Invoke, JNA, ctypes, a wasmCloud host plugin, or inside the Durable Object); see /docs/hosts/in-process/
Durabilitycontract v3: the platform keeps the actor's image in its own store, fenced by an image version, and commits each turn's delta before acting on it; the module is sent only when the runtime asks (409 {needModule})
Costan active in-process actor holds ~110 KiB (was 10.6 MiB); one process held 100,000; activation from a stored image takes ~0.5 ms (was 2.9); a small turn stores ~2 KB (was ~5.8)
Agentmo:ic-agent: query, submit, poll and read canisters over the IC HTTP interface from Motoko, with response verification; moxzi agent-bindings <file.did> writes a typed Motoko façade for a canister
Toolingmoxzi candid-compatible old.did new.did; a library can declare it needs moxzi (a [moxzi] table in mops.toml); mops test can run moxzi; games can ask for the network (capabilities: [http])
Diagnosticsi<22 is a syntax error (M0001), as in moc; forward references rejected where moc rejects them (M0055); M0157 fires inside actor, object and module bodies; M0131 names --experimental-local-actor-persistence when an actor* instance makes a type non-stable; no false M0194 for an import used only in types
Correctnessgeneric self tail calls loop instead of recursing; a library of several declarations is the implicit module moc makes of them (import L "lib" exposes L.A, L.B)
Sizethe compiler is 347 KB smaller (the embedded actor* runtime source is minified)

0.1.0-alpha.6 (2026-09-22)#

Three themes: actor* — many independently addressable, independently upgradable actors inside one canister; a moc 1.16.1 baseline; and cheaper indexed loops and message arguments.

AreaWhat shipped
Languageactor*: an instance lives in one canister's heap but has its own principal, its own Candid methods and its own upgrade story. async* methods are internal (callable with await*, never a message, absent from the interface); async and query : async are external, with a real msg.caller, exposed on the container as Class_method(id, …) so dfx, an agent or another canister can reach a subactor. Actor.id(c) is a principal you can hand out and store; a stale or retired one fails closed. A persistent actor* class keeps its instances, their state and their identity across an upgrade, and they can be held directly in a stable variable — adding a method does not disturb that, while changing a stored variable's TYPE takes a migration function, as it would for an actor
Flagsactor* is experimental and behind two flags: --experimental-local-actors <N> enables it, and holding instances in a stable variable additionally needs --experimental-local-actor-persistence. Without the second, a stable actor* collection is rejected with M0131 … non-stable type, which named the variable rather than the flag (fixed since: see alpha-7). No package import is required — the runtime is injected by the compiler. moc cannot compile these programs
Baselinethe compiler now tracks moc 1.16.1. Programs that use no moxzi extension still compile byte-identical to moc in the reference configuration
Code generationthe checked array/blob index optimization is on by default (--no-index-fast-path restores reference output); --wasm-tail-call and --candid-fast-path are opt-in
Embeddersdeadlines, cooperative slices and checkpointed schedules
Correctnessand/or type operands were judged for forward references in the wrong place: type T = A and { s : S } with S declared later was rejected even though the two records have disjoint fields and the intersection never needs S — which is what kept mo:jwt, and therefore evm.mo, from building. Fixing it surfaced the mirror-image bug, that the union form had no check at all and silently accepted type A = B or C with B/C declared later. A self tail call inside a named nested function — func go(…) declared within another function — was not being turned into a loop, so it took a stack frame per iteration and trapped with a stack overflow around 24,000 levels deep; anonymous and top-level functions were optimized correctly, which is why the effect stayed invisible until a program leaned on mo:core's pure/List accumulator loops at depth. Generic self tail calls (func go<T>(…) calling itself at <T>) were still not optimized at this release (fixed since: see alpha-7)
Runtimethe GC now knows about upgraded static root arrays (a canister that grew its static roots across an upgrade could have them collected out from under it); fuel-backed performance counters no longer drift across budget refills; application stack exhaustion is identified as itself rather than surfacing as an unrelated failure; --compiler <path> pointing at a file that is not there is an error instead of a silent fall back to the search path; upgrading a suspended actor container is refused rather than producing a canister whose in-flight work cannot be resumed

0.1.0-alpha.5 (2026-09-09)#

Three themes: 256-bit integers, thousands of actors on one machine, and verifiable provenance.

AreaWhat shipped
Languagenative Nat256 and Nat128 as fixed-width values (32 and 16 bytes, no allocation for chained arithmetic): the full operator set, wrapping forms, shifts, comparisons, conversions, candid nat on the wire, stable across upgrades. A moxzi extension: moc cannot compile programs that use them; programs that don't still compile to identical bytes
Server + browser--compact-rts (2 MiB GC partitions) so a churning actor collects early; hibernation of idle actors with compressed snapshots and shared module code; a marble-swarm demo with one actor per marble
Provenancemoxzi publish to an ICRC-118 registry with the source digest, options digest, compiler version and linked hash; the compiler canister links its own output and indexes the linked hash; the registry pulls the compiler's attestation (attestLinked) and the CLI prints verified / unverified / DIVERGENT; --previous, moxzi deprecate, --repo/--commit, --gzip; the icrc126-mo package
Registry (astroflora)open publication gated by ICRC-86 domain claims and bought storage (30 XDR per 70 MB, three years); verification badges and a provenance panel in the UI at registry.astroflora.xyz
Runtimea canister that migrated from classical persistence can be upgraded again: classical-heap bytes in the newer metadata slots are validated instead of trusted (stock moc 1.10+ traps with cannot upgrade from an actor using enhanced migration; filed upstream as caffeinelabs/motoko#6363)
Correctnessmiscompiles and wrongly-accepted programs fixed from the fail-suite campaign, diagnostics aligned with moc; --package to a missing directory is M0012

0.1.0-alpha.4 (2026-09-04)#

The release that came out of one question — "does moxzi implement blob:file:?" — and the audit of why the answer had been silently no. blob:file: imports, annotated imports, first-class .size on arrays, ±0.0 literals, Float32 comparisons, Int literals under a Float declaration; shared no longer silently dropped from generic function types; the compiler's crashes on ill-typed input turned into diagnostics. Every fix landed with the gate that would have caught it: the whole upstream corpus compiled and run against 1.14.1's expectations, data segments compared, the test-tree manifest, test/trap and test/fail executed with error codes matched.

0.1.0-alpha.3#

The first public alpha: one compiler, one semantics, four places.

ProductWhat shipped
moxzi (CLI)compiles Motoko by running the self-hosted compiler wasm under wasmtime; build with 15+ moc-compatible flags, link, deps, info, cache, and build --remote
On-chain builderthe same compiler as a canister: per-caller VFS with quotas, ICRC-2 escrow at the CMC's live ICP↔cycles rate with refunds, a mops tag layer, a whole-build cache, self-driven resumable stepping at mainnet caps
moxzid (server)Motoko actors off-chain with IC semantics: atomic messages with rollback, timers, upgrades over HTTP, cycles, actor-to-actor calls with re-entrancy, durable spawned actors, journaled outcalls, kill -9 durability
moxzi-web (npm)the same runtime in a browser, plus a client library: install from a page, call through a dfx generate idlFactory unmodified, persist to IndexedDB, preempt via a worker, make outcalls

Between alpha.3 and alpha.4#

The compiler is at moc 1.14.1#

The compiler began as a faithful port of moc 1.8.2; during the alpha it was modernized to 1.14.1, and its artifacts say so in motoko:compiler. The claim is measured — zero unported upstream language tests, 384/384 mops modules in the top-40 sweep, 359 of moc's own programs behaving identically, and a byte-identical self-compile fixed point that is now a standing gate. The features that arrived on the way: enhanced migration chains with --stable-baseline (see Migrations), moxzi stable-compatible, idl: Candid-interface imports, nested mixins, structural implicit synthesis, bit-exact float literals, warnings on successful builds, and --public-metadata/--omit-metadata.

Verification that shipped with 0.1.0-alpha.3#

ClaimFigure
Corpus programs byte-identical across two compiler builds221
Corpus programs identical browser vs native160, 0 diverging
Native runtime tests81 (cargo test --workspace -- --list)
Behaviour gates16 server, 16 browser, plus demos and compiler regressions
On-chain self-compile177 files, 2,345 messages, artifact 830f3e87…
On-chain evm_engine build661 files, 4,138 messages, artifact 178c6429…

Prose test-counts drift; scripts/alpha_check.sh is the source of truth for what a release actually runs, and the other documents now point there instead of quoting numbers.

Licensing, and the date that matters#

ItemValue
LicenseBusiness Source License 1.1 — source-available, not open source, and we do not call it that
Freenon-commercial use, and commercial development, testing and evaluation
Requires a licensecommercial production use, and competing hosted offerings (a compile service, actor hosting, an embedded runtime)
Change Date2030-08-31 — four years after this release
Converts toApache-2.0, per released version

What is allowed to break#

During 0.x-alpha, treat everything below as provisional. This is not a promise to break them; it is a statement that a break would not be a violation.

SurfaceStability
Output bytes for a given sourcenot allowed to drift silently — compiler_byte_neutral.sh is a release gate. A deliberate change appears here
Diagnostic codes and message textprovisional. M0000 is a catch-all today and may be split
moxzid HTTP endpoints and JSON shapesprovisional
The moxzi-web client library APIprovisional
The compiler canister's candid interfaceprovisional; quoteEscrow() already exists only for older clients alongside quoteEscrowFor(sourceBytes)
Escrow pricing constantsoperator-settable at runtime, and expected to move as measurements improve
Persisted moxzid state directoriesthe write-ahead log format is positional; a format change would require a rebuild from a snapshot
Authone shared bearer token today; roles and per-user keys are post-alpha and will change the shape
Ingress identityevery ingress caller is the anonymous principal; authenticated ingress will change what actors see

Things that are not in this release#

AbsentWhere it stands
stable_sub, the real stable-type compatibility relationunimplemented; moxzid warns instead. See open questions
Off-chain certificatesnot planned — a forged certificate is worse than none
A multi-node moxzidout of alpha scope; more moxzids do not coordinate
CI corpus sweepsthe weekly job is a reminder until a corpus mirror exists in CI; the sweeps run in make alpha-check before a tag
Published crates and npm packagethe manifests are reserved in packaging/reserve/; publishing is a human step

Next#

On this pageHow versions workalpha-7 (unreleased)0.1.0-alpha.6 (2026-09-22)0.1.0-alpha.5 (2026-09-09)0.1.0-alpha.4 (2026-09-04)0.1.0-alpha.3Between alpha.3 and alpha.4The compiler is at moc 1.14.1Verification that shipped with 0.1.0-alpha.3Licensing, and the date that mattersWhat is allowed to breakThings that are not in this releaseNext