v0.5.0 — the declaration becomes an object, the library becomes the App Store
Breaking, and the largest release since the engine existed. Three things moved at once: an app's declaration became a first-class object the engine stores; row deletion became something the engine confirms rather than something every app had to remember to ask about; and an app can now expose a function — a data→data closure the AI can call without rendering anything.
Highlights
- The declaration is an object.
save_apptakesuiandmanifestas separate slots, the stored manifest column is authoritative, and history snapshots both slots —restore_appand undo bring back the pair. A document that still embeds an#oma-manifestblock is refused with a pointer at the parameter. - Deletion is confirmed by the engine, inside the store transaction every tool, batch and widget bridge passes through. Twelve apps used to implement their own arm-then-delete; the ones that forgot simply deleted. No app author writes confirmation UI anymore.
- Functions. An app can declare data→data closures; the AI calls them through
call_functionwithout a render. Bodies are synchronous by design, the seat is opt-in atcreateEngineand absent by default. - The library is now the App Store —
app_store_list,app_store_preview,install_from_app_store, system appapp-store. Oldlibrary_*names are gone, not aliased. The store grew from 17 to 21 ready-made apps, now shipped as directories (components/<name>/{ui.html, manifest.json, fixtures.json}). - Settings and the App Store were rebuilt — the two system apps a user actually sits in, each with a narrow and a wide form, themed entirely through host tokens.
promote_appturns a visual into an app in one call, and edits by range let the AI patch a large app without re-sending the document.- SDK v2. The engine moved to
@modelcontextprotocol/{server,client,node}v2, and a line-by-line audit took the tool surface from 36 to 33. The widget runtime contract bumps tooma.contract = 2.
In a real chat, measured on real hosts
A long tail of fixes came out of live sessions on Claude, ChatGPT and Codex rather than from a test rig:
- A widget's height is now governed by the host: the engine only unpins documents that froze their own measurement (
overflow:hidden,min-height:100vh), so an app that grows is seen to grow — and a card in a conversation no longer nests a private scrollbar. - The App Store no longer pours its whole catalogue into a conversation: Discover is compact in chat, and the only live preview is the detail view you asked for. In the browser viewer, every preview now renders with its sample data (two independent bugs had been emptying 21 of 21).
- A refreshed widget on ChatGPT could come back permanently empty — the host replays a different call's envelope; the widget now writes its identity down through the host's own state channel and recovers.
- Nine store apps crashed on first open in a chat; a filtered app could not shrink back down; the store forced a horizontal scrollbar on narrow widgets — all fixed, each with the measurement that found it recorded in the CHANGELOG.
Upgrading
- A 0.4.2 store upgrades in a single open with nothing lost (v4 → v5 → v6, one transaction each, manifests backfilled by replaying the ledger). Rehearsed against real stores before shipping.
- A store opened by 0.5.0 cannot be opened by 0.4.x — upgrade every host registration and the browser viewer together.
- Hosts holding a cached tool list must re-list: five tools are gone, two are new, four are renamed.
Full detail, including the reasoning and the measurements behind every line: CHANGELOG.md.