Computaco

How it works

Lazy builds: modules, fonts and data on first use#

A one-platform Wasm build (CW_WASM_PLATFORM) is about 13 MB gzipped, and most of it is not the platform: it is the applications, the engines they run on, the interpreters, the services, the internet and the fonts. A lazy build downloads the engine, one platform's shell and the light applications first, and fetches the rest the first time a world needs it:

  • the heavy applications, each a Wasm module of its own, loaded the first time one of its applications is launched;
  • Python, a module loaded the first time a program runs python3;
  • the standard service kinds (mail, chat, wiki, shop, search …), each a part of the engine's own code split into a module of its own and linked the first time a world that declares the kind boots;
  • the built-in internet's world, a data file loaded the first time a world joins it;
  • the thirteen web font families, the other platforms' UI families and the CJK and emoji pack, loaded the first time a frame draws one of their glyphs;
  • the script faces (Hebrew, Arabic, Thai, Devanagari, Bengali, Georgian, Armenian) and the pack's layout stubs, loaded the first time text in one of their scripts is shaped;
  • the web families' metric tables, loaded the first time web text is measured;
  • what only a frame draws with (DejaVu, the platform's own UI family, its icons and wallpaper, the symbol masks) and the renderer's own code, loaded by the first frame: a world driven through its scene alone never fetches them;
  • reading a snapshot back and writing one out, the engine's side of the application modules, the image editors, the debugger and the shell's larger tools, each split into a code module.
CW_WASM_LAZY=1 CW_WASM_PLATFORM=ubuntu bash scripts/build-wasm.sh

pkg/node and pkg/web then hold the engine, modules/<name>.wasm, fonts/<file> (fonts/metrics/<table>.bin), data/internet.json, render.bin (what a frame draws with, one file) and the module host (modules.cjs for Node, modules.js for a page or a worker). Without CW_WASM_LAZY the build carries everything, as before.

What is in a module#

moduleapplicationsfeature
kicadKiCad (with the EDA engine)kicad
freecadFreeCAD (with the CAD kernel)freecad
officeSpreadsheet, Excel, Database (with the sheet and SQL engines)office
videoClipchamp, iMovie, Kdenlive, Video Editorvideo
musicMusicmusic
mapsMapsmaps
codeVisual Studio Code (the frame and menus the shells draw stay in the engine)code
pythonpython3 and its standard library (below)python-module
service-<kind>one standard service kind, 22 of them, split from the engine (below)code-modules

An application module is crates/bindings/app-module built with that one feature: the applications' own code and nothing else of the desktop. Every module has three exports and one import:

  • cw_alloc(len) -> ptr: a buffer for a request;
  • cw_call(ptr, len) -> slot: answers the request (and frees it); slot holds the reply's address and length as two little-endian u32;
  • cw_free(ptr, len): frees the reply;
  • the import cw.core(ptr, len) -> ptr: a question to the core while a call runs. The host passes the request to core(request), which setModuleHost gives it, and writes the answer into a buffer from cw_alloc: its length as a little-endian u32, then the bytes. The module frees it.

The first byte of a question names its channel: 0 is text (below), 1 a program's host calls (Python).

The interface#

The engine serves a module's application as NativeApp::Module, and every NativeApp method is one Call (crates/applications/src/apps/module.rs): the method's name and arguments as JSON. The module answers with the module's copy of the same method. Two rules keep a world the same world:

  • The state stays in the engine. A module application's state is held as the JSON its NativeApp variant writes, and written back field by field in that order. A snapshot, a fork and stateHash see the bytes a build carrying the application sees. The module keeps a parsed copy of each state it has seen, under a number the engine gives that state; when it has not seen one (a fork, a restored snapshot, a module instantiated again) it answers miss and the engine sends the state.
  • Replay loads the same code. The engine is built after its modules and pins the SHA-256 of each (CW_APP_MODULE_<NAME>). The host must answer a module by name and SHA-256 with exactly those bytes. Each step records the modules it ran in its journal entry (RecordedStep::modules), and World::modulesUsed() lists them; a replay, or a restored snapshot, refuses a build that does not serve the same modules.

A render's pixel buffers (a 3D view's picture) travel after the reply's JSON as raw bytes. A call is synchronous: the engine waits for the host, so a host has the bytes at hand when it is asked (Node reads a file; a page preloads; a worker may fetch synchronously).

Fonts on first use#

The thirteen web families (Arimo, Tinos, Cousine, Gelasio, Carlito, Caladea, Lato, Source Sans, Source Serif, Poppins, Montserrat, Playfair, JetBrains Mono; 52 files, 4.6 MB) are not in a lazy engine (cw-render's lazy-fonts). Layout never needs them: it measures with the advance and kerning tables in cw_scene, so a page lays out the same with them or without them. Drawing needs them, and a frame is never drawn with another face in place of one: the renderer asks the host for the file the moment a glyph needs it (set_font_loader) and waits; a file pinned by SHA-256 in font_pack::WEB_FACES is installed, anything else is refused. When the host cannot give it, the frame is refused with render_files_missing and the files it needed, and the next frame repaints in full.

The four platforms' UI families (Inter for macOS and iOS, Open Sans for Windows, Ubuntu, Roboto for Android; four files each) are fetched the same way in a lazy engine that does not draw their platform (font_pack::UI_FACES, pinned likewise): its own platform's family stays, the others' twelve files (about 0.2 MB gzipped) come the first time a page names them.

With a host, the CJK and emoji pack is fetched the same way instead of drawing .notdef boxes until a page installs it.

Render files on the first frame#

Nothing a world does reads what a frame draws with: layout measures with the tables in cw_scene (the advances, kern pairs and line metrics of every face) and a scene names an icon or a wallpaper by id. So a lazy engine (cw-render's lazy-render) carries none of it. The render files are DejaVu Sans, Bold, Oblique, Bold Oblique and Mono, the platform's own UI family, its icons and wallpaper, and the symbol masks; build.rs lists them with their SHA-256 and size (cw_render::RENDER_FILES; a full build embeds the bytes from the same table). The first frame that draws with one asks the host for it, a face through font(file, sha256) (fonts/<file>), an image through asset(file, sha256) (assets/<file>), and waits. Bytes that do not hash to the pin are refused, and a frame is never drawn without a file it needs: it is refused with render_files_missing.

The renderer's code is a code module too (render, below), so the first frame links it as well. An agent that drives a world through scene(), observe() and step() downloads the engine alone; one that takes a screenshot pays the render set once. lazyManifest() marks every render file and the render code module set: "render"; a page's host fetches them before its first frame (host.preload(manifest, ['render'])), as one file (below). A world's state, scene and reply hashes are the full build's whether or not it was ever drawn, and its frames are the full build's pixels.

The render bundle#

A lazy build packs the render set into one file, render.bin, and does not ship the set's files alone (scripts/pack-render.cjs, run by build-wasm.sh), so a client fetches one file before its first frame, not 210 to 216:

u32 little-endian n | n bytes of JSON { "files": [{ "path", "sha256", "offset", "bytes" }] } | the files' bytes

Each file's bytes start at its offset from the end of the JSON. path is the path the engine asks the host for (modules/render.wasm, fonts/<file>, assets/<file>) and sha256 the engine's pin. The bundle itself is not pinned: a host hashes every file it serves from it against the pin the engine asks with, as it does a single file. modules.cjs exports pack and unpack, and modules.js exports unpack.

  • modules.js, preload(manifest, ['render']): one fetch of render.bin, each file checked against the manifest. A sync host fetches render.bin the first time a file it asks for is not served alone.
  • modules.cjs: a file read does not find is looked for in render.bin beside the engine (or the bundle given, bytes or a function that returns them), read once.

Web metrics on first use#

The thirteen web families' advance and kern tables and DejaVu's kern pairs (only web content measures with them) are 1,150,884 bytes (226,091 gzipped). A lazy engine (cw-scene's lazy-metrics) fetches them the first time web text is measured: examples/export_tables.rs writes them, at build time, from the tables a full build embeds (each file is the core's answer to a module asking for the same table), into fonts/metrics/; build.rs pins each by SHA-256 (CW_METRICS_DIR names the folder). Text is never measured with other tables: an engine whose host cannot give one stops, as with the script faces. A desktop that opens no page fetches none.

Script faces on first use#

A lazy engine carries none of the faces text in other scripts is shaped with: the fourteen script faces (Noto Hebrew, Arabic, Thai, Devanagari, Bengali, Georgian, Armenian, regular and bold) and the layout stubs of the pack's faces (Han, Hangul, the Japanese, Korean and Traditional Chinese Han, Tamil, Gurmukhi, Lao, Khmer, Gujarati, Ethiopic, Myanmar, Sinhala): 27 files, 1,199,396 bytes (498,525 gzipped), pinned by SHA-256 in cw_scene::lazy_faces::LAZY_FACES (cw-scene's lazy-faces). The emoji stub stays: every run of text asks it whether a character starts an emoji. Layout needs these faces, so the engine asks the host for the file (fonts/<file>, the stubs under fonts/stubs/) the first time it shapes with one, or a module asks the core for it, and waits. Bytes that do not hash to the pin are refused, and text is never shaped with another face in place of one: an engine whose host cannot give a face stops, as it would without its code. A desktop of Latin text fetches none.

The host#

// Node
const engine = require('./computerworld.js');
const { createModuleHost } = require('./modules.cjs');
engine.setModuleHost(createModuleHost()); // reads modules/, fonts/ and data/ beside the engine
// A page
import init, * as engine from './computerworld.js';
import { createModuleHost } from './modules.js';
await init();
const host = createModuleHost({ base: new URL('./', import.meta.url) });
await host.preload(engine.lazyManifest(), ['kicad', 'lato-regular.ttf']);
engine.setModuleHost(host);

lazyManifest() lists every module, font and data file the engine may ask for, with its path and SHA-256. createModuleHost({ read }) takes another reader (a cache filled from a server); loads() lists what it has loaded and what each took. A host has call(name, sha256, request), font(file, sha256), data(file, sha256) and asset(file, sha256); setModuleHost gives it core(request), which its modules' cw.core import is answered through. A host keeps one compiled module per name and reuses an idle instance; a call made while another call of the same module runs (a python3 a program started) gets an instance of its own, and a request whose first byte is 0 goes to the instance whose call is running.

Text through the core#

A module draws its windows, so it measures text, and measuring needs the advance and kern tables and the script faces text is shaped with (Noto Arabic, Hebrew, Devanagari … and the pack's stubs): 1.25 MB of faces and 1.5 MB of tables, which every module used to carry again. A module carries neither (cw-scene's core-text). The first time it measures with a table or shapes with a face it asks the core on channel 0 for that one (cw_scene::tables), keeps it for the life of the instance, and measures with it locally. The core answers from the tables it measures with itself, so a module lays out every line exactly as the engine does; a test reads every table back through the wire and compares it with the engine's (tables::tests).

Python on first use#

python3 is a module too (modules/python.wasm, crates/bindings/py-module): the interpreter and its standard library, 1,898,156 bytes (577,546 gzipped). A lazy engine is built with python-module instead of python and loads it the first time a program runs. The program runs in the module; everything it does to the machine goes back to the core through cw.core on channel 1 (cw_modules::script): its files, the world's network (HTTP, DNS, TCP), child processes run by the machine's shell, the clock, entropy and the thread scheduler's seed. The engine answers each call from the host of the run that is waiting, so the run's journal records the same calls as in a build carrying the interpreter, and an interactive session resumes by replay as before.

A child process that runs python3 again is a call of its own while the parent waits: the host gives it another instance of the module. Under the debugger the module asks the core at each stop, and the engine's debugger inspects the stopped program (threads, frames, scopes, variables, evaluation, assignment) through calls back into the module's running call: a request whose first byte is 0 goes to the instance whose call is running (cw_modules::REENTER). A test runs one program, and one debugger session, both ways and compares output, files, requests and everything the debugger saw (crates/core/modules/tests/python_bridge.rs).

The first program costs the module's read and compile: 30 ms against 23 ms in the full build for the first python3 -c; later ones 0.4–0.7 ms more than the full build's.

Code modules#

The modules above are programs of their own that the engine calls. A code module is a part of the engine's own code, split out after the build and linked back into the engine's instance the first time one of its functions runs:

code modulewhatcrates
service-<kind>one standard service kind (mail, chat, wiki, shop, search …), 22 of themcw-service-<kind>
webthe HTML engine, the browser, and the runtime of the web applications (Notes …)cw-web, cw-ui, cw-browser, cw-tsx
javascriptthe JavaScript engine pages and node run on, with Node's librarycw-jsvm
sqlitethe SQL engine sqlite3 runs oncw-sql
renderthe renderer, the rasterizer and the image decoders, and the scene renderer a page drives (SceneRenderer)cw-render, fontdue, jpeg-decoder
snapshotreading a snapshot back (import, restore, fork) and checking it, with the parsers of every type of a world's state; writing a world out as JSON (an exported snapshot, the owner's inspect)World::{import_snapshot, restore, fork, export_snapshot, inspect} and their kernel and environment twins
app-callsthe engine's side of the application modules: the parsers of what a module answers (effects, scenes, pages)cw_applications::apps::module::ModuleApp
imagingthe image editors (GIMP, Pinta, Paint, Pixelmator, Sketchbook)cw_applications::apps::imaging
debuggerthe debugger of programs and its protocolcw_computer::debugger
awk, sed, git, archive, find, datautilsthe shell's larger tools, one module eachcw_computer::<tool>

web also holds the web applications (cw_applications::web_app). A module is named by its crates, by a path in a crate (paths) or by a function (functions); what only its functions call follows it. The JSON code the engine's own types need stays, once.

A lazy engine is built with all of them (services), then split (scripts/split-modules.mjs, with binaryen's wasm-split --multi-split, binaryen 121 or later):

  • Which functions. A function goes to a module when it belongs to that module's crates (its path, or the type it is a method of, is theirs; a service kind before the HTML engine its pages are written with), and so does every function only that module's functions call. A generic of the standard library or the JSON code instantiated for a module's type is placed by its callers alone: the compiler merges identical instantiations, so one named for a page's type can be the one the engine calls for its own. A function that belongs to two modules, an indirect target no module's crates own, and a function nothing calls directly (an export) stay in the engine; so do the few a world runs whatever services it declares (each kind's register, kind and version, asked when a registry is made), so a world fetches only the kinds it declares.
  • What every world runs stays. A desktop holds a browser's state from its first boot, and hashes, snapshots and forks it. Before splitting, the build runs the unsplit engine, instrumented (wasm-split --instrument), on scripts/split-workload.cjs: the agent-desktop world drawn as the build's platform, its own applications launched (not the browser or a web application), input, the semantic channel, a snapshot, a fork and a restore. The functions of web and javascript that run keep their place in the engine (12 do), so a world that never opens a page, a web application or node never links either.
  • Which data. A module's constants (its pages' stylesheets and templates, its strings and tables) move with it. The linker's map gives every data object's address and size, and its relocations (--emit-relocs) every pointer in the data and every address the code uses. An object moves to a module when that module's code is the only code that points into it, directly or through other objects. The engine's segment loses the bytes and the module gets a segment that writes them back at the same address when it is linked, before any of its functions run.
  • Linking. The split engine imports a placeholder for each function it moved (cw-code.<module>). The glue (crates/bindings/wasm/js/link.js, patched into wasm-bindgen's JavaScript) answers the first call to one by asking the module host to link(name, sha256, engine): the host instantiates modules/<name>.wasm against the engine's exports (its memory, table and functions), which puts the module's functions into the table in place of the placeholders, and the glue makes the call.
  • Pins. The split writes each code module's SHA-256 into the engine, in space the code-modules feature of cw-wasm reserves; the engine gives them to the host as host.code and lists them in lazyManifest() with kind: "code", and the host refuses other bytes. A code module only fits the engine it was split from.

The split moves code and data and never changes them, so a split engine runs the code a full build runs: its state, frame and reply hashes are the full build's, and a step records no module for a service. Its kinds keep their state in the kernel as any build's do.

What it costs. The 22 code modules are 1,223,654 bytes gzipped together on Ubuntu (a kind's module 21,271–122,221), against 5,206,825 when each kind was a program of its own that carried the JSON, URL and protocol code again; that code is the engine's, once. A world that joins the internet declares 19 of the kinds: its first boot fetches them and the internet's world, 1,421,081 bytes gzipped (from 4,866,795), and takes 112 ms against 86 ms in the full build (from 311 ms). A world of the company's own services fetches only the kinds it declares (the agent-desktop world: service-wiki).

The internet's world on first use#

The internet's world (worlds/internet/world.json, 1,268,250 bytes, 292,636 gzipped) is not in a lazy engine (cw-internet's on-demand). The first time a world joins the internet the engine asks the host for data/internet.json by name and SHA-256 (computed by crates/internet/build.rs from the file it was built with, so it cannot drift) and parses it once. A world that sets internet: false never asks; a world that joins it without a host is refused with internet_unavailable.

Measured#

Release Wasm with the size flags of scripts/build-wasm.sh, GNU gzip -9, on gb10-direct, 2026-10-28, at the commit that changed this table. The engine is what a client downloads first, and all a world driven through its scene ever downloads unless it uses an application, a service, a page, a program or a snapshot that needs more. render.bin is what a client that draws fetches before its first frame (every file a frame draws with and the render code module), and "first render in all" is it with the engine. Times are the first frame's of the agent-desktop world after a scene-driven session, in one process each, on the lazy and on the full build.

platformfull build: rawgzipscene-only boot (the engine): rawgziprender.bin: filesrawgzipfirst render in all (gzip)first framefull build's
ios37,359,58813,233,8075,412,6901,765,6032102,154,9581,310,6973,076,300139 ms123 ms
ubuntu37,448,91213,310,4815,413,4491,766,2912152,256,5471,399,6583,165,949304 ms283 ms
android37,453,90813,328,9525,383,8491,762,3952112,248,8751,406,0023,168,397143 ms130 ms
windows37,471,50413,344,6455,385,1131,762,4792142,260,3961,421,2823,183,761323 ms302 ms
macos37,947,84713,808,5765,443,7241,778,7902162,727,2671,880,2423,659,032302 ms281 ms

Before the render bundle (07296489), a first frame fetched only the render files it drew with, one by one: 15 to 41 files, 0.61 MB (iOS, Ubuntu) to 1.18 MB (macOS) gzipped. The bundle is every render file in one request, 1.31 to 1.88 MB gzipped. Before cw-encode the engines were 1,782,156 (Ubuntu) to 1,798,566 (macOS) bytes gzipped.

So a device driven through its scene downloads 1.78–1.80 MB first; its first screenshot adds 0.61–1.18 MB (2.39–2.98 MB in all, macOS the most: its wallpaper is 0.77 MB). How the lazy Ubuntu engine came down (gzip): 8,771,353 with the applications and web fonts lazy; 8,774,781 with text measured through the core (the modules shrink, the engine does not); 8,307,694 with Python a module; 7,036,852 with the services a program each and the internet's world a data file; 7,058,221 with the services code modules (the JSON, URL and protocol code they share is the engine's again, once); 4,887,082 with the HTML engine, the browser and JavaScript code modules too; 4,411,126 with the script faces and stubs fetched on first use; 4,215,094 with sqlite3's engine a code module; 4,043,370 with the other platforms' UI families fetched on first use; 2,885,882 with the render files fetched by the first frame; with render, snapshot, app-calls and debugger code modules 2,439,718, then with imaging, the web applications in web and the shell's tools 2,057,287 (these two by the split's own zlib -9, about 1.5 % above GNU gzip); 1,782,156 with the web metrics fetched on first use.

A world that joins the internet (the harness's unrelated lab with internet: true) fetches the internet's world and 19 code modules at its first boot, and web with the web metrics when it first lays out a page. On Ubuntu the first page a desktop opens costs about 15 ms more than in the full build (linking web), the first node -e 12 ms more (linking javascript), the first sqlite3 3 ms more (linking sqlite).

The application modules, Python and the data file are the same bytes for every platform:

modulerawgzipfirst usefull build
kicad3,329,063935,563launch 30 ms9 ms
freecad3,195,351907,600launch 18 ms10 ms
office3,747,6181,085,403launch 16 ms (Spreadsheet), 3 ms (Database)9 ms
video2,253,961684,805launch 14 ms (Kdenlive)8 ms
music1,854,281537,118launch 13 ms8 ms
maps1,555,543451,362launch 11 ms8 ms
code3,042,001909,796launch 17 ms8 ms
python1,898,032577,482first python3 -c 30 ms23 ms
data/internet.json1,268,250292,636an internet world's first boot (above)

The code modules fit only the engine they were split from, so each platform has its own; they are the same size within 0.1 %:

code modulesrawgzip
app-calls191,794–199,18150,073–52,141
archive45,067–45,06817,843–17,853
awk127,197–127,19943,071–43,085
datautils47,692–47,69316,506–16,516
debugger99,246–103,12028,170–29,152
find26,416–26,41710,574–10,582
git108,560–108,56135,931–35,941
imaging572,776–573,052180,206–180,325
javascript2,693,016–2,693,024917,247–917,302
render564,352–567,145194,617–196,045
sed41,602–41,60316,818–16,823
snapshot698,694–708,813164,023–166,992
sqlite633,964200,730–200,754
web4,642,468–4,660,5451,282,721–1,285,830
service-*4,024,251–4,027,5281,213,370–1,213,976

Fetched fonts, the same files for every platform: the script faces and stubs, 27 files, 1,199,396 bytes (498,525 gzipped); the four UI families, 16 files, 414,256 bytes (266,372 gzipped), of which an engine fetches the twelve (eight on macOS and iOS) of the families it does not draw.

A first launch is the launch step in a fresh process on Ubuntu, the median of five: the module's read from disk, compile and instantiation (3–6 ms of it), the tables and faces it asks the core for, and the launch itself. Before text went through the core the application modules were 1.24–1.87 MB gzipped and their first launches 25–35 ms. A first frame costs 2–12 ms more than the full build's. With eight module windows open, a step takes 9–18 ms against 4–7 ms: each window's render is a call. The web fonts are 52 files, 4,583,364 bytes (2.76 MB gzipped); one face is 25–159 KB.

The SHA-256s the engines are built with (lazyManifest() lists them). Every platform's engine pins the same application modules, Python and data file:

module or fileSHA-256
codec4989d7b00eec7b2e038f9a1bf5adfb1b850896d3841ddd769a6ef2a9cb4660e
freecad112cac580a5cd4f3130f3071bdea46a938f418d5ec9f128c33d791fde011ea5d
kicad86ed2fbb0ca759e65d7037eb3dfac9196c8631e16e0ead004019b86d41e45a5e
maps20e26eac2c449d88bf3e60c398805f6b6b8dfea5a9a68c9804966962d4d2a757
music44abde50e5ffec95bf73e83fa42974196f0c760084f40e920976e50cb892c107
office3eef5488066a8cb3552c98fc49605c78f6fc0fa7bdc509eba0e9c1d129956cab
python8d8635e86dcc5e8af1a4ae66b761e5dcdaed7b0404d6a1fe9f62e1a788d20c76
videoa1ee744bcf56602e54098408bc331581e714a7c62d21502b6d295106ef14c67b
internet.jsonf9ab3f53b17c1cf696e38275694cec0b36db152b9d94ade627636c4b000775a6
ios: the engine and its code modules
fileSHA-256
engine01a96c2629a6767ed279b18b10b20364819d361392abefa5bdc6c92a76124aee
render.bin9266c370b4c46a3ee9048f741676d26c48d1cc82b4ab820cb738b080bd60e8e2
app-callse8190c286bcccdc4eec4da0012ea2fff10860c6bbe47a95eb4490e774957c95b
archivec3d60ffc22ff6838cb2a240cf818f82ad924dd143ee234ecce2ba25b39478d5f
awk758d2cd915f0e450ba196f982d04f835daf610bb27ca91cf1c70bcabcc2b494e
datautils010962abc65a5ca6dadbf488dc4e3df0f72cdc4815edd47c465ea7884f2d9d29
debugger0d3ea7f7adcc29b53d0a9c83b6465f24639e64084c952f8114434154a5d6c4a6
find22fbadbfe512c63afab56752da2b5a4d88520b0ae3614f2c91de07f72a7c4961
git2b3c60f85221bec6c655e78b341230ec9b70091c95145528b38418b2bcfabcbd
imaging9608fc866df77bbfdfbc6ee3ad3ae4cb4025cf46eeb5e52b443f79068ca66cee
javascript7ea65884b3d9d8498acbf6d1fc96096411c393f787068886f96628f5705d79df
renderee817c633b21febfd4c74ac13352b6bb94db53c78e9c667f88f6bdf2f4d4087a
sed6e13efcba71438f3f77c348eeab1f87a88770394d117f10af22af54f14545c4c
service-assistant1a90397572804f042f62b2c62b8dd9cc0ce52188ed7a26fbe23d1fc6e273a9e1
service-bank30e7c77282435a6a4a114b69508c9e8ae6dcfdc11f788151a031f6152f474c8c
service-calendar0dacd692ae2aa73621004b8fdcb41f4dd4ff6dc304b2217a00cce4c1653f6238
service-chat5a41cb3d024e482d30e6c6738702cdb15be9283495de49e8b30be4760ca0eb69
service-discordc757e42fc3d23362d3885f100361cbb771404198041b2a4d1a082c315065c66e
service-docsbcea21613ab44293c8b618490dfbeae97e26f3c17d675ad3a9c0d6d0efd1315a
service-drived6d293a52d61a84d6db65819264baa6f16008538008e4bcf36014ac3f1435dd9
service-forum4025c1cb1ddeaa6b18d54d4ed012f15f00b8b56d50b921b86ffa240dad2c2c39
service-geo529a32062d8da43a39e825797679ac7ee1d2d43c981f6ad5869e0133731ed9d6
service-git7f562bb1a701e5a66ea6422ffcd7ed234ccde9a34dbe99a2443b03d9d6055493
service-issues7560fcfd30e83e0c4d44c891e20c5b9328f9c6195fcfbc0e46847ab308ca45bb
service-mail5b375dfb6a466d6fad6761335d0b6acb8fcb5844cca70e612259870e06a497a5
service-mediac9e7d2b1af367682fd105bea75bab83467635ff1021a2136f7a35ff9f73416c9
service-messages6176b116c4e80be884e78e23ca76c9f14a488b708051955e6ded4e3162039d39
service-presse80982c4d417b3b3fdc94fdb468180c16d18c6d818c187c2bc48e3fb784c531d
service-searchbc23332d4f293436de2f6e9f947cc35cd1a7b44922b49d5aeb9f530013b596c0
service-shopab095c83854dff78949ff45e6ede06a71290a450dfd0086c969c36b29b18d135
service-slack744f6c0f69706423aeb491306e2c03e76fdf57dc98237012146fda83236d089f
service-social8b48783274cc5a23dd14c0900f575083d8ca858f96166808a6e1d76659153f26
service-speaker304d3e5eff6691bde4f5c9ed6d57f6374e47c15d7cdbcceba11fdadea03867d7
service-static-siteee14a95ae4f71c00c61ea3beb6ffa5147b2a5a784bbfaad6b7b196ca37bd8db3
service-wiki8d04e800042d5bd46cb795ee25cac4e7aa8999a768e5a1ce5213613485cf60c7
snapshot5ba451c8f011e63c52b9e6302176676d24cdb1e10bf1860ff4adc9c87e397f84
sqlite6710294c63f4501b363639a801e4fee94ea8c2abee1ab02b3a3a99161b625e1c
webd3ba0c8b50082e530a49963d0db091e6730ac605f0f8cee7045c3e2b7656c2ec

</details>

ubuntu: the engine and its code modules
fileSHA-256
engined709735702eacdf8308e5a6964c9ac5092d382568cc6b74eb6c5a5a09c65a30b
render.bin5a979b861f0729e21eaf7a8f504829910e6097574ca369c875bacd2160d94252
app-calls5801a5c27198233d8e3584d9a654b8f2b20911dceaaa0655ad72c3d30659f649
archive51dde54fd39586a9c5b7207bb976efe0ba58c75fcd33370b514411fb4b829ba2
awk673bb16c10652b5932e01709aa24dbec3fc9b17b566bc4d66172ae639474d089
datautils425dfb7c3e57114784e64f4322edb5cf9e54c56e4b187cf18024cc2395cc7233
debugger6b8eaadafa86bd86831293a380d23b2705688d14bbeb0096f6c659b5e04ac811
find78a67849551f86cfa3c1838c1d2551943a35d852834515381ffb0149c959bd50
git0a4bb22424024a31e9ebace7bb5c9f6870169beac5fba9fcc8f3a3b0514aa336
imagingf8d24d65ac2bfa346e72878dc20c0fff0d4a85a5b3f992d88adda1b0468d9eeb
javascript1b85f83a96139bdb85d6a479b4d5f057a12d2d8cde5e2a901be37967dfefc311
render1e257d1b72899d7f7b90fcb676a6598f30fcc0bede847f9daebcdbe890a45731
sed31fb11843ff0dd275eae5347d9dc6c4234ef54c6ec3ef03b55374b090383ad5c
service-assistant3a4e0d919fd936ea3a23bbca8105708c465e9a3c3259f389f44f6080c335292d
service-banke89454ed8b31da95931c08d54c56e35d20140b7b026d2e4f29b9124cb884f396
service-calendar2c06c37fd3021587eeebae77f931b6d2e58985b30d3122711f7007dde8818ba4
service-chate697a057807d6392d2e10cd490bbbd48e5c157b5eb54563c5394cba8973ddf8f
service-discordad3d8e47a05b38211185874d1fd87bce116e3e36842dc066da4913f776231931
service-docs99bbecacc4529cc256e3c4a9ffe010347b0d42515c13a1c612eb48e3346859a0
service-drive9a1accb79eae1d68066c836e8449ac1a811b43364b65bd9fb3f87e305056080b
service-forumfb2ab95f73832f9aca4a8ee32821e3429e32425f2b3a69959e46d9ad39f31b12
service-geo99e5b4259c9a5344d334419132310050e920d2390489d945e4be47f7bd5d09df
service-git6f504fc0c40508edc7d4c5f7f797f127960fd8214eba2cbc2df487023529940c
service-issuesea01cefdc63345f10cd1f5da4d64ff393c05c9505ff096740bc8770d1ab16801
service-mail6cff511353e605da33ce867e97ff124bb689bfc3075ac8c1c3a74b0327d5bf57
service-mediada3d5dd2f428e5f96eaa40345384553a040fc446a0471de777adfe7bc02f90d6
service-messages417c49ae780df8a0fe85cc9f0b21f497d8cad2b184cde0bbf8ff92cb162de093
service-press1ad0bd5f70ad0835c35c2afb14de54c9ce69bb4cbe77dd07600c93983b61c73e
service-search10fc72dce7b26d3a14f9622a1dcb6b174540b720b565eb9370b769d8fb5259fe
service-shop553fb0bae4729eba0a236fb2b547c3780a40d8acf36c26bf646a205c954eb1b1
service-slack17a5207bf87b823494023122d0ee229cf9fef87390688d37bdd0fa086c7bc6ee
service-social8bf3fb85a6936aad20e23417036cf7b831b29e4cb7da1246d165bde636a5bd26
service-speaker3a51e4ec8cdbabb25f44804ccd7dfb12332a7467d4538246c4aff792abbf1781
service-static-site0ca4a2fff0dab8d97e1b74df42b46ee255e2bb2f986b347233aec074053dc6d5
service-wikif915dd45d125f0fa3a8a275613b7c88c3de4a9ff9878f7160d35eef31a4f1a57
snapshot616f493fae65773490bb21da65a512d4d3641c81cab7174d507ce9d95e8cb877
sqliteae16658827268dbf1481003cd6e22751615424a4dd16b9763f43569c6a73fe79
webfca2bb32bd5cd00abe68d6fb607af5ed16da0899a17a85b1fe420db070b21d16

</details>

android: the engine and its code modules
fileSHA-256
engined01bb1af89cd27e5166657bde43bd5b14686a74b7d1a897b9e32e51ebef032a3
render.bin905f05a2455eb6cacef29cd6f0d8736f852e89a9961278402dd4d2f7a2495692
app-callsf2ea77bc7c199db2a1a1efcd4f833dfd7ca0e4ffe40d5f76cf8d303ecb8cbf29
archivef74b471f91b03829c12100a599ce4629d46465d44e06dc94d5377dec328ff94a
awk0093302c2d6d2459667f944c558aeb52e66c35a6fd027b0a3ed0850a829324f1
datautilsad330094ce97c31205454d71cc9fcb69f1021cce94e77ef8a0b9ab9dfc374d26
debugger62fe6f4f1860ea7296ee03d1a4b632abd686964dcae257efcc61411d79279d14
findbb23fd8aa01904057b2cae310cbbe81728bb406a5e6e22e76f34ebf90ed49337
gitebaa59857a61fbfb986506b11f36279b9526c7482964e766c44c6d30c5c93a26
imagingb8422b91ce5d4c04b899e8733a5d3ad3700ec8dc5ca3c6f3dc574ef352c8d49b
javascriptf14e889d377ea2a4f122edbd3632004f80a6dc407b80ea3a87c2095458d4f57e
renderac55c492eaecda334bd86e1dfadf37d9663d5a2894925a193cf20ea770f997a7
sedd467eb1207d75bd268318274189d096198a71314fa8044107bbfa30343451124
service-assistant079b4b85efd62cfd22bb7e3f679b0676407a4dec620ce22972a28b67c65462b1
service-bank2488930912e6f77fbb14544e556162594515cf725dae7214f1e59cafb31fba5b
service-calendar4c29b514218a4c19b3435d9e3102ea279c6b1684e59d65136fe8dfcaa763236a
service-chat943831b144aabfbecc7b17b44ce13cd390159f99154e85cb0304572f0a9bdbf5
service-discord00754568f31659170cb4b236e9473e4bf25e8fe5405ee457d049957d93def3ce
service-docs823ba025bef54c4f9bcceaa4986e8b996171d372121a91aabe255bd2712b03d9
service-driveeb972178d46e48a48b194474fb31c845a1132f7de0d15f5e9c840df7a302194b
service-forumd09a6665fca1e33b039da24ee8254e0d0fabaae85a5ca5457cacac9b0f5415a5
service-geo0120975d0440ddab3e9289e5dd8af5bfe14ee45bb79e1f1eaffbbfd90650cbb5
service-gitdc072f8083378c8504faca35810273d0be1d3b6e2af3a64f079f8e16b4d75807
service-issues46f082ad2a22e8169a368bada8d6c97352620da411d92c4273d37e4f3d489264
service-mail11b592d4937a02dcf554193877e4df1aea7db8cca0ecb7fb575340dd046c7231
service-mediaa1f4af3e3ac91927a1868eb55659ba1fae35b80965868bdb24dbe348776b6567
service-messages3c53122a6c889817c0e7ac401c13522812593d03a71ff78e18cd43d64a2a3681
service-pressbefa9c16e4a9f294de0af992ed57bb7cbff5d0c1d56c4fab642f477f36e2fda4
service-search7dc3e214c200c148b7df69f561554a145c20b367ea9a000996933ad8de095279
service-shop1cd18893ac0b7007367c350b0fcddc58262a317cba4e0b77a90e8c1b40b61584
service-slackab3fa3d6db6c64b9844924d2005a5e358498813f5a787961289dd82e2dea03b1
service-social849f2e70e678854d0553bf0b9d43806256b5faff873e3d2e7136bfe81b05c9d4
service-speakerc438cb1f64a1e1113e3f37ee43daad41635ae0288a595d6ea2c1331220664925
service-static-site7a4e0ab0eb8c871e8e56847ccf0ce7afb81da84fad1e9ef64b378bc1168baca0
service-wiki815436d3f145e0907443619913ad87e979f2b4fc7b3b26225c207b8f84029cbf
snapshot9652bbe01509944a471b976bfb6f4bdc17fd7f0b2716b778bfbe38c84f6f9734
sqlite4b0cc28962ada37d0eecef890112c490271473b8895fb7f10fdb2a13d7f4b5e6
webd6b400b900d94a5e957989fef5f94386561dfe7fc65911c470074cff2748590a

</details>

windows: the engine and its code modules
fileSHA-256
enginefb3285893bcfb9abf7684cd0393e0202c43aa64974589182aa340ff5ca33612c
render.bin265be7cb954854a94a6147b95bc4506ac59ccbdc68b8270324d8887766533fea
app-callsc197e102a3ed61788e464e7f88f2e83cddd30c5c76c97f0ff134453f804283be
archive6e51078165ce07e77a7787700beee5b688119a300959520a6ebacbf9e577b9b9
awkd5a4b4cd9abcf751b35e84276d05911652fa779111e7e18eb16a49b7195494ca
datautils5c47deba7e29e4469df7653e5ae748d0c12cf3e7e55108dc1887cf6b4eb36bb4
debugger41f87a37371683f24698a85c7514b43b89edf1a6c339c77c383339ffb99f791a
find757d00da38917c6ef107f10fdd75c0b4dd1a2a9cd3d631b6e61b87c1f2929819
git6056e02b73a7f44fc822b12d568658bbbaced84b7bf42ee2dbc1ba9dab29ffa0
imaging1167b5bcf814f95cfd26e62d40b3059f81da03899c8c5d42da971bc40266a31e
javascript8ae2496483d964cfde154118489b108b6eeb47af6e4622347a47e6b3be5f1020
render2d6229bac0dcc90b6cdb36f5304fbd52e080b16a6510904b922e194aecd482dd
sed63658e0c16f2bde08d2c292b19aa8f7a14a401bff11259f3a87c6bce6b949259
service-assistant44988f307061c44e70824fc399655ac53a89e12e4431265b09116571ad569e2b
service-bankf54c730553d8a051b6473076ede725f0a5b094a3c1b1abb533e9e38f12a93cc7
service-calendar4036b857fcb64a116c3ce714e012333719bf350c003bb1ab338e3f67a9d91d68
service-chat3bba3e759d7473b21db352993af3fb4702ed9a628c552c2a2659a3c1a62a2ec2
service-discord99b91b6daeab31cc82e9ee2070caf23a5d4c78d3001cdfb624ec19e3614f17c2
service-docs2b866007e105aa07fc2c04bcb8523414361c50829622552c6c0d65d7e8ebb56d
service-drivef43a44cc874dddf880aca8965db4bf2a318721272c625dcf90930156bd8de1d7
service-forumc42d0f098c717fe9c216b236717608873e5b0eb7101f193fc1e2a40008356775
service-geof1d073a69232ee17e7cad65e1cf34c4820c6f19fc94ab571a2c5ebd767a7d9b7
service-git81973c3ea8cb27680e7caf6ec9f5a60e957edf033a4f5005ef7c361d4f5392c7
service-issues77f58679334fc54aa7c2f4599edbf1de940074645120e89b5c4a50980f03e74e
service-mail1d4e6b9637d0ec8afbd6d8ad6c29cc04a4918dc1a50c7fd7aa76ce599b043443
service-media0287ea659e5178f6b2f973241412253a584d4d0d2a17da756988f716d37390de
service-messagesb3e920b547f4cfaed0edf90f85ffd7577c8c124f3c58833fb499a8fec195c6b0
service-press1240e90828822e84623d495fe7ac34fa9e1b125c085b7693327f0c71eab7dc5c
service-search0492ab3d25e0f179404077428ff8fb22bb8ad977f83b084b5cbd55beff586172
service-shop4ddff4176603d15a50a66bd6e22ae69fae88c66acc0fc7b074f5a2771cac5dce
service-slack06bb9338fad624888eb03b5b0450768eebc2e0bd218ab5251a790726d2580b38
service-socialab1d3f483dc7dae3d88f2e2220cff9bde7ff2e07121e8bb2d9e7851ceceac7c4
service-speaker5398b434039c26f953b1a91fd7e568e0a4982a229fe3a585e57641d9ab911a78
service-static-site87122078075d39d9b9e4e017a4a32e51554e532117cd5bb58fb9feb71e7d16dd
service-wiki071685812d4b80ada898ee781e86fc1b01ed6d86e923f0c9e8f2379432c32ba9
snapshot4c622560cc010433429ac30423978237d22167c8f511c643659467a97f2c4b14
sqlite6ad7f20989728ef2d4cdaeff7620490843abe5fe1e20f5665fc3ec911f2967ec
web39a631ddc9a63d141337b2e99e8fc2bb8fc9ac6827895aa0d09232303d9e0b4a

</details>

macos: the engine and its code modules
fileSHA-256
engineb0ea9b3f64174af1628e8bdc17ab8ad4fb1336ad5e2ca78bfa0fab08a5eb6ad3
render.bin220eb32d3bd360cfce3064ecbece4d04305eb5d3d6ef50cb93ff2031003b04de
app-callsdd4e65c17f1970eef045689451a0f7b05da7b095f9d0b225cbc975c21693d05c
archive1b6ca8c342032f0191cb01a93304277e8f612e181404f560f6b7b3fd08943da3
awk928c7bc1853c473b07f291746f83ddf6fbaa0f7a315c157dc9da788b40061e08
datautils1f08e49d50b2c501a0d3b86282f0999ccd7a50c72d4f7d4b3c07b27308b7a1ac
debuggerd65f7e64b8a0aa1a4f9468189352b669e1b2ee4b3c40cdf6d34920dc667fe71e
findee91986cf7f7d4edb3a78875fd102e4f09cc7147440c0bc1e5b4eabc1302ae04
gited19232db10d132a92aca9874b5c346ffa31d59b58147faba96f04991f9548ed
imaginge082ee5b148bd2e98d77fcd7cbec3e31d75838253a5834f37f7fa96c4b1d8684
javascriptce335acbc966a485e260795fe2739a93993aaba98d5240756529ce32eaab4413
renderc738359fe73e2e89aa4616c4e32ef0f23388abe5b983c0688e0ccc44991b2a46
sedaf86a27161e8eb8cf6805e09871d38c0bafa1574e76d8a21d652c1d1d5c336e9
service-assistantccd740c27408a9131a61bc8771df3fa12bb8cd22a171b187106c30ca156bf7c8
service-banke7e4c85e5525f725b30283ba0bfc8cec5b11449399945c6c775c3273e19cff05
service-calendarc240c9c7dad85429bfb8febd14444922d6e70b018d7a390559be3c8fbabc4617
service-chat0c7803b8d944a10dea490fce378893e010509409cc3c522a8eeb54735f3e13b5
service-discord3c7a789f57b4aac3c03672512a1efee087867b74c7ad1e42d8415e06a193bf09
service-docsf78e04f00d138336ea2dc88ac13a2b814f0ef92ce54c61d26cdfc344c4f0dd71
service-drive57e4bf2acc82b1e9233511064dcf26d04a455ba6d4b34f9e7a5a139d9ec5055f
service-forum5bf5b0a413943c65658554dc1dd291d1a4b4e060ef887c9c09efed0a8c540188
service-geo2ca29c523378bbba7d0b72916a8cbbeeadb8e88af3a04ab1cd7d3d1891c85025
service-gita7279f4638f2116d2fd1cfbff6f086c716a34442c48c4ae3c9cac2923fafeb81
service-issues5be727b43d6a9f67cec2b9e2f471600ca5486490e1c83f1d180ab072371fcf2f
service-mail5ca2b426c97f27c9cb8eae86dd0136b19e9141206d79a10db388f6b649483f89
service-media4d427520c71c60cb3051d5c4c1f2501123096acb4a341fe3aaebc1b5a987138d
service-messages30a5e9d83dc0014d53d63cee944204e9307cc550335e491f6159d06675b2c363
service-press0ebd9e80f6ad5b2ee43700e26f78f2ae38acb5e058e2d600f00143477cdc5b5a
service-searchfc33c813ba2066964a0019963858def1396474803978e2a2076b2e45f106a7fb
service-shop29db419523cfdc695c2e28bdc01e442546edac6b8db2f34c0c08a62fb9b6961f
service-slack34f3a039c857607e8d0053e0cf0a2c45c0128ab848d46394e9dcf7c1ed9a965f
service-socialc387529eb665486cdf2ac8c714594a6ae06835f5b9f21d2fbb91ee92c05809b8
service-speaker8a60024df3bf541c63acd6a90c82f57ff92b436465db599d5e174e0201d80fb0
service-static-site52fe57886e3ca800836c49627a60ef108887335ab9c6acf6e5f8c47ebb386b35
service-wiki45a045fcd11475f2de3a47b634b54f31469d6f8cf7272ed11a52cab5aaa9a09b
snapshot68dab50b4be1ed6c1392c145a85f7000ba2b9d1a6089bd754aa9a0ddde12a95a
sqliteabe5e268d8e837b8bada12a85f101c916bd3845b9aba2a70a48e6967e9190fdd
web56b835173e88d6ad12c2441ef75047bfeb05f44c62ce3be30d7b9a00cf60500a

</details>

The equivalence check, on all five platforms (bench-style harnesses run on the full and the lazy engine of each, comparing every hash): the agent-desktop world launching all eight heavy applications, clicking and typing in each, then python3 in the terminal (a -c one-liner, a script that writes a file and starts ls, an import error, an interactive session), node -e, sqlite3 and a line of seventeen scripts and an emoji in the terminal, then the browser: 89 of 89 state hashes and frame hashes equal; and a world that joins the internet, every site's front page asked over HTTP, six sites opened and drawn in the browser: 91 of 91 state, reply and frame hashes equal. Both snapshots round-trip. And the desktop's scene drawn again in each of the four UI families gives the full build's pixels, the families the build does not draw fetched on first use. A scene-driven session (bench/scene.cjs: boot, the scene after each launch, click and typing, a snapshot exported and imported, never a frame) gives 23 of 23 state and scene hashes equal and fetches no render file; its first frame then fetches them and equals the full build's.

What the first download still holds#

The lazy Ubuntu engine (1,766,291 bytes gzipped) is mostly code. The data is mostly the tables layout measures every desktop with (the platform families' and DejaVu's advances, the script coverage and the emoji stub), Unicode's tables and the regular expression engine's. The code is what every world runs: the kernel, the shell and its everyday tools, the light applications and the platform's shell, layout and shaping, the code that reads a world's definition and its actions, and cw-encode, which every step's hashes are taken with. Attributed by name (CW_SPLIT_NAMES=1), serialization was 368 KB of the engine's code before cw-encode (a serde_json::Value tree, JSON text and the scene digest's JSON, three copies of every state type) and is 257 KB after: cw-encode 121 KB, the Value serialization of replies 87 KB, the rest small. The deserializers, which read a world's definition, actions and the modules' replies, are 552 KB (119 KB gzipped alone): the largest serialization code left, and the next lever. What left it, on first use: the heavy applications and Python (modules of their own); the service kinds, the HTML engine with the web applications, JavaScript, sqlite3's engine, the renderer, snapshot reading, the module calls, the image editors, the debugger and the shell's larger tools (code modules); the internet's world (a data file); the web families, the other platforms' UI families, the script faces and stubs and the web metrics (fonts and tables); and everything a frame draws with (the render files).