Skip to content

v0.5.1 — an app stops being a guest and starts owning a screen

Choose a tag to compare

@2nd1st 2nd1st released this 15 Aug 11:34
· 8 commits to main since this release

An app stops being a guest in someone's conversation and starts owning a screen. 0.5.0 made an app's declaration a first-class object; 0.5.1 asks the next question — where is this app standing? — and gives it three answers: a card in a chat, a page it owns, or a region inside a host's panel. One contract covers all three.

Highlights

  • The stage contract. Every app used to hand-roll its own outer card, hero header, root width and overflow policy — 7 different frame styles and 10 different width values across the store, double-rounded corners on phones. Now the kit owns the wrapper: in a chat the app gets one standard conditional card (and on narrow frames, none — the host's widget frame is the card); on a page or panel it renders bare, edge to edge. Apps declare their width posture in one manifest word (stage.width: column | wide | fluid), and all 22 store apps have been rebuilt to the contract — decorative identities (gradients, rings, accent bars) moved into content, where stripping the frame can't take them.
  • @live — a brick, not a route. A display that follows whatever the AI opened last is now a primitive: any app can place oma.embed("@live"), and the engine keeps a single overwritten pointer (schema v7, deliberately not a ledger event — opening an app is a glance, not a data change) and pushes it over the existing SSE channel. The store ships a ready-made Live Display app: install it, open /view/live on a spare tablet, and the screen switches by itself as the AI works. Apps that contain @live declare stage.display and are excluded from the pointer — a wall never points at itself.
  • Panel hosts are first-class. Two opt-in URL words for anyone embedding /view in their own chrome: ?chrome=0 (no viewer bar or stage — the panel draws its own) and ?nav=intent (app→app links become an openmcp:open-app postMessage instead of navigating the frame — "open X" is a request to the host, not this page's navigation). Embedded child documents now inherit their parent's context, and stage.display apps render chrome-less on /view by default.

Fixed, found on real devices

  • No sandboxed child document had ever reported its height — a minified-bundle name mismatch landed in the broadcast's own catch, silently, since the runner shipped. Every embedded frame sat at 140px forever. One line; frames now size to content.
  • Forms inside embedded apps couldn't submit at all: the sandbox lacked allow-forms, and Chrome refuses the submit event before dispatch — so every onsubmit handler (17 of 23 store apps hang their add/edit on one) never ran. Granted, with the actual submission still triple-walled off.
  • Apps taller than their frame couldn't scroll in fixed-height contexts: seven store apps pinned overflow: hidden on the root, which is correct in a host that grants height and a dead scroll wheel in one that doesn't. The viewer now unlocks the root; the apps handed in their declarations.

Upgrading

  • A 0.5.0 store upgrades in place on first open (v6 → v7: one added table, one transaction). A store opened by 0.5.1 cannot be opened by 0.5.0 — upgrade every host registration together.
  • Tool surface, oma.contract, and the runtime API are byte-for-byte unchanged from 0.5.0. manifest.stage is optional and additive.

Full detail, including the measurement behind every line: CHANGELOG.md.