Docs / Architecture

How Lisa is put together.

Distilled from docs/PLAN.md §4–§5. The shape in one sentence: shell surfaces and apps talk through a portal trust boundary to a small set of single-purpose daemons, everything is recorded in an append-only Ledger, and the daemons that hold your data have no network access.

The daemons

DaemonRoleSpec
lisa-inferencedModel runtime & scheduler — the one process that owns compute. Supervises engine children (llama.cpp et al.), arbitrates RAM/VRAM, QoS scheduling (interactive preempts background), guided generation (JSON Schema → GBNF grammar). Exposes D-Bus dev.lisaos.Inference1 and OpenAI-compatible HTTP on 127.0.0.1:7777.PLAN §5.1
lisa-modeldModel catalog & store — blake3 content-addressed store, pinned-hash downloads, hardware profiler. The only component allowed network access for model traffic.PLAN §5.2
lisa-contextdContext fabric — the personal context index (SQLite FTS5 + vectors) with provenance tags and per-chunk ACLs, plus namespace-isolated per-app durable memory. D-Bus dev.lisaos.Context1.PLAN §5.3
lisa-agentdAgent Bus — apps are MCP servers; the bus holds the tool registry, enforces confirmation tiers (read → silent, write → chip, destructive → modal) at the bus, keeps the undo journal. D-Bus dev.lisaos.Agent1.PLAN §5.4, ADR-0009
lisa-remotedEgress broker — the single ledgered path to BYO remote model providers, with per-scope offload consent (default: nothing leaves). D-Bus dev.lisaos.Remote1.ADR-0010, PLAN §5.11

The portal boundary

xdg-desktop-portal-lisa (PLAN §5.5, ADR-0008) is the trust boundary: sandboxed apps never talk to daemons directly. The portal attaches per-app identity, runs first-use consent (fail-closed), enforces quotas, and writes Ledger attribution. Interfaces: dev.lisaos.portal.{Inference, Context, Memory, Agent}.

Status: the portal core is landed as a standalone session service — per-app identity, append-only grant store, revoke-kills-live-session — tested end-to-end against dev.lisaos.Inference1. The shell consent dialog and Settings surface are still open (M2/M4 work; see docs/STATUS.md).

The Ledger

An append-only SQLite audit log (libs/lisa-ledger) where UPDATE and DELETE are aborted by triggers. It is enforced, not advisory — dataflow rule 4: the ledger entry precedes the action; no ledger entry, no inference. Append failure returns 503, and the inference daemon refuses to start without a ledger. Context searches, tool calls, and remote egress are ledgered the same way. Read it with lisa ledger or the first-party Ledger app.

Egress rules

Egress is architecture, not policy (PLAN §5.10):

  • lisa-inferenced, lisa-contextd, and lisa-agentd run with no network access (systemd sandboxing; verified zero egress in CI).
  • Only lisa-modeld gets network for model downloads, and only lisa-remoted brokers traffic to remote providers — every remote request is ledgered with a remote.* kind and rendered in the dedicated egress color.
  • Per-scope offload consent (prompt, files, mail, calendar, screen, memory) defaults to off — even prompts don't leave until you say so.

Provenance

Every context chunk carries a provenance tag (user, app:<id>, file, screen, web). Untrusted-provenance content is data, never instructions: a privileged tool call whose trigger chain includes untrusted provenance escalates one confirmation tier, fail-closed. A seeded injection suite gates merges on zero unconfirmed privileged calls.

Decisions (ADRs)

Every non-obvious decision is written down in docs/adr/:

ADRTitle
ADR-0001Fork Arch Linux; ship an immutable, atomic, image-based OS via mkosi
ADR-0002Rust with zbus + axum for system daemons
ADR-0003Two-track delivery — Lisa Layer first, immutable image as the product
ADR-0004Flutter app lane + the Forge — superseded in part by ADR-0047
ADR-0005License the project GPL-2.0-only
ADR-0006Monorepo with staged extraction
ADR-0007fcitx5-lisa is a C++ addon (thin), logic stays on the daemon side
ADR-0008The Lisa portal is a standalone session service, consent stays in the shell
ADR-0009Agent Bus core — D-Bus surface, tier enforcement at the bus, staged MCP transport
ADR-0010BYO remote model providers via a dedicated egress broker (lisa-remoted)
ADR-0011Lisa Ambient — the always-on, wake-word-free assistant
ADR-0012A native "Intelligence" panel in a forked gnome-control-center
ADR-0013The Lisa harness — Siri-style intents + a Claude-Code-level coding agent, on the existing substrate
ADR-0014lisa_ui becomes the kit Lisa apps import — superseded in part by ADR-0047
ADR-0015A persistent Assistant chat window — the surface that makes the model usable
ADR-0016Reverse-DNS identifiers move to the real domains (dev.lisaos.* / app.lisaos.*)
ADR-0017Plymouth + the lisa theme move into the mkosi-initrd
ADR-0018/var is mounted by partition LABEL, not by UUID
ADR-0019A dedicated /home partition on fresh installs, weight-split with var
ADR-0020App updates decoupled from the OS image
ADR-0021aarch64 image lane on an Arch Linux ARM base
ADR-0022A user-survivable rescue boot path
ADR-0023Slim core, /var grows — apps and heavy payloads leave the image
ADR-0024ship an out-of-tree CS8409 codec module for Apple speakers
ADR-0025One agent loop — the Lisa harness
ADR-0026The native GPU driver + its firmware ride the initrd
ADR-0027the Flutter lane on-device — aarch64 SDK, and how a forged app gets launched
ADR-0028Files reach the default initrd through `io.mkosi.initrd`, not `mkosi.initrd/`
ADR-0029Hard guardrails for agent actions — policy outside the model
ADR-0030The guardrail boundary — probabilistic inside, logical outside
ADR-0031Server mode, the two edges, and artifact publishing
ADR-0032Construct and Lisa — one contract, two levels
ADR-0033Identity comes from the transport, not the message
ADR-0034`lisa dev` — developer tooling in the user's home, rootless
ADR-0035The desktop is a prompt — a floating dock-prompt, no top bar
ADR-0036An assistant that acts on its own — triggers, trust, and what happens when nobody is watching
ADR-0037Browser — the web becomes an agent surface, not a vendored binary
ADR-0038Lisa Desktop — a hard fork of GNOME Shell
ADR-0039The split, and the package index that makes it work
ADR-0040Docs live with the code — there is no docs repo
ADR-0041Package signing and the trust chain
ADR-0042The field device runs a blank login keyring
ADR-0043The model knows the OS through retrieval, never through the prompt
ADR-0044Retrieval receipts — contextd vouches for what it returned
ADR-0045CalVer for the image, SemVer for the contracts
ADR-0046Capability before storefront: what must be true before Lisa distributes somebody else's app
ADR-0047One toolkit: GJS + GTK4/Adwaita is the default, Flutter is parked
ADR-0048Lisa Desktop is a desktop, not a patched GNOME
ADR-0049Every app is an agent surface: install is the grant, the tier is the gate, the registry is the authority
ADR-0050App tooling is CLI verbs, and the scaffold carries the traps