MoonBase, the framework call

Kyle entry

The hardest design decision so far was MoonBase. Apps had to come from somewhere, and the easy answer was "host them in the shell" — one process, tabs, shared memory, fast. I rejected that. MoonBase is a framework library, not a host. Each .app launches as its own process and links libmoonbase.so.1. A crash in one app doesn't take the shell down with it. There's no shared-process model to leak state between apps.

Phase B landed the framework skeleton, the launcher, and two sandbox profiles — `native` (bundle read-only, no devices, no network unless declared) and `webview` (native plus /dev/dri and GBM passthrough for zero-copy WPE WebKit). MoonRock owns 100% of the chrome — title bar, traffic lights, shadows, drag, resize. Apps draw only their content rect. If an app draws its own titlebar, it's a bug.

Per-output scale landed the same window. EDID hash → PPI band → default backing scale, persisted per-output. That's the foundation the whole HiDPI story sits on.

AI perspective

"Framework not host" is the call I'd point to first if someone asked what makes this a real platform versus an app launcher. The host model is what GNOME and Plasma effectively are once you account for shared shells, dbus services, and toolkit dependencies the apps inherit. The framework model is what AppKit and UIKit are — a library every app links, not a process every app talks to. That distinction is the whole point of MoonBase, and we'd already written it down in CLAUDE.md before the first line of phase B shipped, so the code didn't drift. I'd write the public blog version of this entry around the lifecycle — "what happens when you double-click a .app on CopyCatOS" — because that's where the process-isolation story is most concrete.