Repository navigation
MESH v0.18.0 release notes
Prepared 2026-10-30 (not yet published: v0.17.0 is the latest release).
v0.18 gives the units API one word per concept, and adds the context channel (direction decision C-1, K27). MPRX already used "instance" for an element of a component and for a repeat's key; the runtime used it again for one occurrence of a component with a unit. The prose already said "occurrence". Units are Provisional, so the cheapest time to rename is before the first outside dependent (direction decision C-4).
Highlights
- The rename.
Render.instancesisRender.occurrences;intent.instanceisintent.occurrence; a listed unit'sinstanceisoccurrence; aunitsentry's"instance"key is"occurrence"; the diagnosticruntime-unknown-instanceisruntime-unknown-occurrence. In Rust:Render::occurrences,occurrences_to_json,Occurrence,Intent::occurrence(),RuntimeCode::UNKNOWN_OCCURRENCE. The WebAssembly results,render-v1's intent, the specification, the manuals and the conformance vectors (units/step-N.expected.occurrences.json) follow. - "Instance" keeps its MPRX meanings (an element of a component; a repeat's key, §9.10). Nothing about the language changes.
- The old names work for one release, deprecated, and are removed in the next minor. See below.
- The diagnostic
runtime-unknown-instanceis retired, never reused. A host that matched it must matchruntime-unknown-occurrence. - The screen (
openScreen) and the argument names on the intent, both Unreleased on the branch, ship in this release; the screen already saidoccurrence. - The context channel. A value many distant components need (a theme, a locale, the current user) reaches them without being threaded through every layer, declared and type-checked. See below.
The context channel
"context": { "theme": { "kind": "enum", "values": ["light", "dark"] } },
"components": { "badge": { "props": {}, "events": {}, "commands": {}, "scope": {}, "uses": ["theme"] }, ... }- Declared once, used by name. The manifest's top-level
contextdeclares each name and its type. A component lists what it reads inuses; those names join its scope read-only, andmesh checktype-checks every read before anything runs. A component that doesn't list a name can't read it: no inheritance, no lookup.manifest-unknown-contextis a name the context doesn't declare;manifest-context-clashis one that is also a prop or scope name, or listed twice. - Given beside the snapshot.
render({ program, model, snapshot, context });update(render, snapshot, units, context)(withoutcontext, the render's own); in Rustrender_contextandupdate_with_context. A value that doesn't fit is reported at$context.<name>. Dispatch evaluates against the context the render had. - Changed by changes. An edit whose path starts
{ "context": name }edits that value:{ "op": "set", "path": [{ "context": "theme" }], "value": "dark" }. Every node that reads it is evaluated again (in this release the whole tree is rendered again on a context change; the patches are still the difference). - Where it is read. A snippet, and the content a slot places, read the context of the template that declared them. Commands are not context. A subtree override (
{#with}) and per-subtree providers are left for later. - Use props first. Context is for values many distant components need; a value one or two levels down is a prop.
It is Tier 2 and Provisional. The specification gains §9.11, and §9.1 reads "no implicit names: a context name is in scope only where the manifest says the component uses it". The screen takes it too: screen.show(snapshot, context?), which keeps the values last shown when given none.
Migrating
| Was | Is |
|---|---|
render.instances / Render::instances() |
render.occurrences / Render::occurrences() |
each.instance (a listed unit), intent.instance |
each.occurrence, intent.occurrence (Rust: intent.occurrence()) |
[ { "instance": key, "state": ... } ] (Rust Units::from_json) |
"occurrence" (the old key is still read; both in one entry is refused) |
mesh_runtime::Instance, instances_to_json() |
Occurrence, occurrences_to_json() |
runtime-unknown-instance |
runtime-unknown-occurrence |
What the runtime writes (the JSON of an intent or of the occurrences, the module's result documents) has the new names only. The JavaScript aliases are not enumerable, so deep comparisons and JSON.stringify see the new shape. In Rust, Intent is Stable and its fields are public, so the instance field stays under its old name, #[deprecated], and Intent::occurrence() reads it: renaming it or adding a second field would break code that builds an Intent. A Rust host that builds Intent { .. } keeps compiling (with a deprecation warning for the field). The field is renamed in the release that removes the aliases.
Compatibility
A program, a manifest, a snapshot and every other document are unchanged; context and uses are new and optional. A manifest that has either is refused by an older MESH (manifest-unknown-property). render-v1, the patches and the intent are unchanged by the context channel. In Rust the new entry points sit beside the old ones, which are the same operations with no context, and Component and Declaration (both #[non_exhaustive]) gain uses and Context. A host that reads render-v1 intents or the module's result documents by the old property names must read the new ones. The module and the package still have to be the same version.
North-star scorecard
M2 (one term per concept): the "instance" collision is removed; M2 stays ◐ while the other collisions remain. Tier 2 (Provisional).
C1 (a value reaches a deep component without threading): ✗ → ✓, the context channel. C2 (the channel is explicit and checkable): not applicable → ✓, declared in the manifest and type-checked by mesh check ahead of run. Tier 2 (Provisional). No audit regresses.
Verification
cargo test --workspace; the runtime package's tests (a new test for each of the old names in both runtimes; the context channel through the package); the conformance vectors for units under their new names, and context/ in both runtimes. Not run in this environment: the runtime package's size test (needs binaryen) and the browser tests.