The decisions ledger
This is a curated index of the load-bearing decisions — roughly thirty of the ~104 on
record — grouped by the layer they govern. Each entry gives, in one line: what it
decided · why · and its reversal condition where that is notable. The full decision
files live in decisions/NNN-*.md in the base repo; this ledger is the map, not the
territory.
How to read this ledger
Three conventions carry a lot of weight, so read them first:
- Current truth vs lineage. The app-model and serving spine moved decisively in
mid-July 2026. Present d/100 / d/101 / d/102 / d/103 as current truth (plane on
127.0.0.1:5454, plain-http default, super-apps opt-in). Earlier serving decisions d/078 and d/080 are lineage — superseded on the port and the HTTPS-by-default ruling. Where they conflict, the higher number wins; the ledger says so at each entry. - Proposed markers. Two decisions are PROPOSED / pending Luke and gate real work: d/103-B and d/104. They are flagged inline and collected in Proposed / pending Luke below. Nothing downstream of them dispatches until Luke disposes.
- Tension with code. A short list of decisions currently in tension with the code that is supposed to implement them is kept honest in Decisions in tension with code.
Foundational / mission
- d/041 — Dogfood Xe as the daily driver; unsigned personal packages allowed behind strong consent. Decided: run Xe as Luke’s main OS on a fresh machine; self-signed / AI-authored personal packages are first-class, gated by a strong consent surface (not a gatekeeper). Why: real use beats demo; the safety layer is consent, not a store. Catalog-source signature enforcement is unchanged. The Internet Archive / Brewster backing is “warm.”
- d/062 — Delivery scope: peer topology, mobile both-track, resident agent, weeks-not-months. Decided: multi-device is peer (not hub-and-spoke); mobile ships in two tracks (v1 phone-as-remote-client, v2 Android runtime); darc → Reagent is the resident agent layer; the P0 line is the IA/DWeb circle on mac + Linux, in weeks. Reversal: peer topology is the costliest steer to reverse once sync formats ship — flag format decisions loudly.
- d/068 — Finish line = the demo-day bar; peer-sync v1 is metadata-only. Decided: “done” means Luke and Jan can run install → open → wake → update on a fresh mac and a fresh Linux box from the quickstart alone; peer-sync v1 scope is source pins + serial anchors + receipts/ledger only — volumes stay single-home. Why: a checkable, unambiguous finish line; a deliberately narrow first sync.
Runtime / browser
- d/008 — Xenon is a fork of Helium. Decided: our browser forks
Helium (a de-Googled Chromium); GPL-3.0
inherited; patches layered in
patches/xenon/; build order Linux → macOS → Windows → Android; no GitHub Actions (Folknet is the build infra); Android is a separate greenfield track. The Isolated-Web-App gates are three Chromium flags to flip on desktop. Why: start from a maintained de-Googled base, add only what IWAs need. - d/061 — Helium is the confirmed Xenon base. Reversal: if Helium stalls against IWA needs, fall back to a vanilla Chromium fork.
- d/057 — Browser provider matrix; Xenon’s value is “IWAs without flags.” Decided: the launcher runs IWAs in stock Chromium-family browsers via a CLI-flag recipe; Xenon’s differentiator is that IWAs work without flags, not exclusivity; browser choice is a user-visible setting. Reversal: if Chromium breaks the flag path, flagless Xenon becomes primary.
- d/003 — Blessed install path = launcher + bundled Helium. Decided: the narrated primary path is the launcher with bundled Helium; own-Chrome is the secondary path. Empirically IWAs install on every engine ≥ 140; older engines fail; unmanaged install is silent but two-step (install, then launch).
- d/053 — Naming and Boot Service architecture; darc → Reagent rename decided. Decided: the canonical names (runtime / Boot Service / console / Xenon / app engine) and a zero-resident-process Boot Service; the darc → Reagent rename is decided but executed later by Jan. Open: the IWA → Boot Service wake-channel mechanism is still undecided — an unauthenticated loopback TCP socket would be disqualifying by our own standard (see the design frontier).
App model / spectrum
The July-16 wave that set the current app model. See Mission & principles for the two axes these encode.
- d/075 — “Super web app” is a class, not a product. Decided: no Prism-privileged APIs; every surface Prism uses must be a grantable platform contract; super web apps are interchangeable like browsers or window managers; darc is the proof of concept, Prism the first platform-native instance.
- d/076 — The app spectrum L0–L3. Decided: one substance (a web app), one axis (granted capability), no cliffs; L1 = installable unmodified and un-Xe-aware as a hard promise. Why: if installing required “integrate with Xe,” the model would be broken. First real-app target: Patchwork.
- d/082 — The agency ladder. Decided: the rungs from nothing up to super user agent; every rung is consented, receipted, and undoable; permission denied is a first-class state, not an error.
- d/091 — Agency ladder v3. Decided: the driven rung goes live over the Chrome DevTools Protocol; composition becomes generative (pane A + pane B → new artifact C); the canonical demo is a live re-skin.
- d/081 — Xe-generated IWA wrapper as a native-window shim. Decided: an Xe-generated IWA wrapper can give an L1/L2 app its own window, icon, and dock presence; the wrapped app stays unmodified and gains no capabilities. Status: recorded, not scheduled; watching Chromium’s IWA sub-apps API.
Serving plane / origins
- d/077 — Each installed app gets its own subdomain off localhost. Decided: apps
present at
<app>.localhost, origin-isolated locally and over iroh; composition panes load origin-served subdomain apps, not other IWAs. Why: use the web’s own origin isolation instead of inventing one. - d/078 — Serving ratifications (partly lineage — see note). Decided: the router
is workerd, pinned and launcher-managed, with
a route table generated from installed-app records;
<name>.localhostnaming with collision suffixing; no cross-app CORS, ever (same-origin policy is the isolation model); router privacy default (lifecycle events only, no per-request logging); every device runs its own router, iroh connects the routers. Note: its ingress:5196is superseded by d/100/d/102; the rest stands. - d/080 — Local app origins over HTTPS via a name-constrained local CA (partly
superseded). Decided: local origins served
https://<name>.localhost:5196via a launcher-managed, name-constrained local certificate authority (DNS.localhostonly). Status: the HTTPS-by-default ruling is narrowed by d/101 (plain-http default); the name-constrained-CA machinery remains valid for cases that need it. - d/092 — Bundle-header policy: honor-by-default. Decided: the platform parses an
app’s
_headersfile (the Netlify/Cloudflare grammar) and applies it to that app’s own origin; the one refusal class is headers whose effect would escape onto sibling apps or the platform (e.g. a parent-scopeSet-Cookie Domain). Apps run unmodified. - d/079 — swbn/IWA packaging reserved for L3; L1/L2 delivered as catalog rows. Decided: signed web bundles are for L3 Controlled-Frame apps only; L1/L2 apps ship as a signed catalog row + content-addressed static payload; example apps live in their own monorepo, never inside a super-app’s repo (that would re-privilege them, forbidden by d/075).
- d/100 — The Xe local plane port is
127.0.0.1:5454. Decided: the plane binds5454(Agent54 → 54:54); guest origins arehttp://<app>.localhost:5454; it is a local-only consume plane. Reversal: collision with common software → it stays configurable. Current truth. - d/101 — Two app tiers; plain http(s) is the default. Decided: regular apps are served plain http(s) and isolated by the Controlled Frame; swbn/IWA is reserved for super-apps. Why: isolation is already delivered by the Controlled Frame, so a per-app IWA rebuild would just be a store-like gate against the litmus. Load-bearing — the current app-model spine.
- d/102 —
5454is the user-facing plane; the internal peer forward stays5198. Decided: the plane origin is5454; the internal workerd → iroh plumbing keepsPEER_FORWARD_PORT = 5198— using the same value causes an address collision in the integrated fleet path. Why: a “fix” that merely narrowed the failing test was rejected; the port split is the real fix. Current truth. - d/103 — Compose-driver app UIs are plane-origin proxy routes. Decided (Item A):
a compose app’s UI is a whole-origin proxy route on the plane, framed by Prism like
any app — not a per-app Controlled-Frame target. Proposed (Item B — see below):
whether that becomes a distinct
container-originroute type or overloads the shippedbackend-proxytype. Note: a code comment on the rendering model still contradicts this (see tension list); reconciliation is part of the gated implementation.
Isolation / backends / engine
- d/028 — Untrusted workloads get a VM boundary (amended 2026-07-18). Decided:
third-party / untrusted workloads run behind a VM boundary; weaker rootless containers
must be labeled visibly (an
isolation_classfield). Amendment: the standalone microVM workstream is retired and rescoped onto the smolvm-backend track (d/051 + d/094); the VM-boundary-for-untrusted principle stands. - d/094 — Backends reached through a socket the app engine itself publishes. Decided: the backend connector consumes a host unix socket provided by the app engine — no per-app sidecar, no loopback TCP; smolvm gets the capability first as an upstream-quality contribution. Why: fewer moving parts, a cleaner trust boundary; retires the earlier sidecar options.
- d/050 — macOS packaging discipline. Decided: never
codesign --deep; sign inside-out; two-layer pinning (download pins in git, installed pins stamped after signing); only Mach-O binaries in code locations, data trees under Resources. - d/027 — UCAN-compatible delegation semantics. Decided: capability delegations
carry UCAN-compatible semantics (signed,
attenuable, decentralized chains, attenuation-only), while invocations and receipts
follow a Xenon profile; the full UCAN wire format is deferred, with the profile
documented in
ucan-mapping.md. Primer — UCAN: User-Controlled Authorization Networks, a way to express “you may do X on my behalf, but no more than X” as a signed, chainable token that needs no central server to verify.
Transport / peer
- d/014 — iroh terminates in a native local worker; self-host the relay before
production. Decided: iroh runs in a native local
worker (not inside the IWA); the public n0 relays are dev-only; a self-hosted
iroh-relayis required before production; iroh-blobs first. Primer — iroh: a peer-to-peer transport that dials a device directly by its public key, using relays only to help two peers find each other and to fall back when a direct connection is not possible. - d/046 — Minimal iroh fork with a single visibility commit. Decided: our
agent54/irohfork is upstream + one commit exposing a network-change hook; explicitly temporary. Reversal: upstream the commit, then repin vanilla iroh.
Distribution / forge / governance
- d/007 / d/025 — Forgejo on the NAS is the forge of record. “The forge is home” — the git host we own is the origin of record.
- d/013 — Forge-first push policy. Decided: agents never push to GitHub; GitHub pushes are Luke-approval-gated, per push. Why: work products live on infrastructure we control.
- d/098 — HARD RULE: no AI drive-by PRs to external repos, ever. Decided: agents never open PRs on non-Agent54 repos; humans publish contributions; the agent role stops at a reviewed branch + drafted PR text. Why: precipitated by an external PR withdrawn the same day; publishing is a human act.
- d/067 / d/064 / d/065 / d/066 — The trust chain. Publishing is a signed static catalog (d/067, Ed25519, serial-anchored); the console is the witness (d/064); distribution stays cluster-internal until Luke flips it public (d/065); key custody: the orchestrator holds catalog/release seeds for the build phase, with the production key ceremony pending (d/066). Primer — Ed25519: a widely used public-key signature scheme (RFC 8032); a serial anchor ties each catalog release to a monotonically increasing number so rollbacks are detectable.
- d/099 — Retire
docs/map.html. Decided: the old structural map is replaced bydocs/state.md(narrative) and an orchestration-board artifact (structure). This documentation site is the successor review surface.
Mobile
- d/042 — iOS companion: full member and management surface, app-opening delegated. Decided: the iOS companion is a full group member and consent surface (consent-on-the-go, Devices/Activity, notifications) sharing the Rust core via Swift FFI; the IWA / Controlled-Frame shell is the platform gap, so opening apps is delegated to Safari. Android companion is the parity target. Note: iOS is client-only by Apple policy, not by our architecture (see the design frontier).
Proposed / pending Luke
These are not yet decided. They are recorded here because downstream work is gated on them and the review session must dispose of them.
- d/103-B — Distinct
container-originroute type, or overload the shippedbackend-proxy? Security-critical: it widens the connector boundary from a single/apiprefix to an entire third-party app’s origin. Gates P-210 (the compose / Immich UI). Luke ratifies at the P-210 charter. - d/104 — The Controlled-Frame guest launch seam = the catalog launch descriptor. The proposal: the guest a frame launches is resolved from a runtime/catalog-owned launch descriptor (app label → plane origin) on every platform — no per-app baked guest URLs. Escalated when an installed Android Prism could not repoint from its baked guest to the plane origin. Unblocks Android in-frame render and offline honesty. Luke disposes; nothing dispatches until ratified.
Also awaiting Luke, though not numbered decisions: the authed-wake questions (AW-1..AW-5) and the d/053 wake-channel mechanism.
Decisions in tension with code
Kept honest so the review does not mistake intent for reality:
- d/080 / d/078 (HTTPS-default,
:5196) vs d/100 / d/101 / d/102 (plane:5454, plain-http default). The scheme moved from HTTPS-default to plain-http-default and the port from5196to5454. d/080’s name-constrained-CA machinery is still valid, but its “HTTPS is the product default” ruling is narrowed, and d/078’s:5196ingress is superseded. The site presents d/100/d/101/d/102 as current truth and d/078/d/080 as lineage. - d/103-A rendering-model contradiction (inside the decision). A code comment on the
MarkUirecipe operation still says “Controlled Frame UI” (a CF-per-app intent), while d/100/d/101/d/103 mandate plane-origin rendering. Reconciliation is part of the gated compose implementation. - d/094 vs launcher code. A
BackendProbe::Ready(SocketAddr)path is stale TCP and must be reconciled to the engine-unix-socket contract; the related sidecar PR is held pending this. - d/028 amendment residue. Any code or doc still describing a standalone firecracker/microVM lane is stale — read d/051 + d/094 as the living successors.
The review agenda
Ten questions for the Luke + Jan review session, each with one paragraph of context. The Big Picture and this ledger are the reading for these. (These ten are the ledger-level cut; the consolidated running order for the sitting — these plus every Part III session question, de-duplicated — is Part IV’s review agenda.)
-
Ratify d/104? The Controlled-Frame guest launch seam as a catalog launch descriptor. Ratifying unblocks Android in-frame render, offline honesty, and the dependent mobile work. The alternative on the table is an explicit Prism/IWA launch contract with install-time guest manifests. This is the single architectural proposed item blocking the mobile in-frame story.
-
Rule on d/103-B. A distinct
container-originroute type versus overloading the already-shippedbackend-proxytype. This decides whether the frozen route-table schema changes, and it gates P-210 (the Immich compose UI). It is security-relevant because the container-origin path exposes a whole third-party app origin through the connector, not just an/apiprefix. -
Movable memory and exit-without-loss — commit a format now, or stay single-home? Two sovereignty-litmus clauses are only half-met today: app data is single-home (sync moves metadata, not the data inside apps), and
xe exportexists as intent, not a proven whole-machine round-trip. Deciding whether to commit a per-app export/import format now is a litmus-touching call for Luke. -
Schedule the production key ceremony. The trust chain is closed in code, but the production signing keys do not exist yet — the orchestrator holds only dev/build-phase seeds. The offline split-custody ceremony (Luke + Jan) gates all public distribution. When does it happen — after Thailand?
-
Pick the Boot Service wake-channel mechanism. d/053 named the IWA → Boot Service wake channel but left the mechanism and its authentication open; an unauthenticated loopback TCP socket is disqualifying by our own standard. Candidates: loopback + a per-install token; IWA Direct Sockets with an authenticated handshake; or OS socket activation (launchd/systemd/Windows service triggers). A design packet should precede implementation.
-
Multi-user / groups / sharing — in near-term scope, or explicitly post-camp? Everything today is one user’s own device group under a single-writer group doc. There is no decision covering sharing an app or data with another person, multi-writer docs, or multiplayer. The DWeb / local-first audience will ask first; the current plan defers it (“recruit the CRDT people at camp”). Confirm the deferral, or scope it.
-
Confirm the HTTPS-vs-plain-http local-origin truth. Confirm that d/101’s plain-http default fully supersedes d/080’s HTTPS-default ruling for regular apps, and that the name-constrained CA is reserved for the cases that actually need it — so the site and the code present one current truth rather than two.
-
darc → Reagent rename timing. The rename is decided (d/053) but executed by Luke + Jan. Does the review-session material and near-term copy say “Reagent” now, or keep “darc” until the rename is actually performed?
-
Schedule the self-hosted iroh relay. d/014 requires a self-hosted
iroh-relaybefore any production peer traffic; the public n0 relays are dev-only by policy. This needs a human packet (a container + DNS + TLS) before production peer serving. -
Approve journal unification. Some grant/trust records are standalone JSON-lines logs sitting outside the hash-chained audit journal, so the console’s Activity view cannot witness them — an inspectability-litmus gap. Approve folding them into the hash-chained journal as a work packet?