Minimal, immutable, API-only Linux distribution (appliance) whose sole purpose is
running Astromesh AI agents (astromeshd). Versioned v0.11.0 (semver, like the
rest of the ecosystem), mature through Phase 4 + post-4. See the
documentation and the design
docs in docs/superpowers/specs/.
The roadmap (docs/superpowers/specs/2026-06-05-astromesh-os-decomposition-design.md §4)
is implemented through Fase 4 + post-4, all merged to main:
| Fase | Capability | Gate |
|---|---|---|
| 0 | Astromesh-core as a systemd service; boot-to-agent | phase0-ci (boot + agent, per-push on main) |
| 1 | Minimal image (~378 MB of real blocks) + OCI publish via ORAS | phase1-publish |
| 2 | Immutability: dm-verity RO root, A/B + automatic rollback | dev-loop update |
| 3 | Security: TPM-sealed secrets, no-shell + break-glass, AppArmor, tool sandbox, egress, Secure Boot | phase3-tpm, … |
| 4 | Agent-native + fleet: machine-config, mesh mTLS/IPsec, OTel export, eBPF causal egress | phase4-{machineconfig,mesh,otel,otel-metrics,ebpf-rust,ebpf-control,agent-egress} |
| post-4 | §12.3 cgroup memory governance, §12.7 CRIU checkpoint/restore, §12.2a sched_ext¹ | phase4-{memory,criu,schedext} |
Runtime pinned to astromesh v0.55.0 (runtime.pin). What that carries for an
API-only appliance is mostly cost per run: an agent called as a tool now returns its
answer instead of its whole run — its steps and trace used to be stringified into
the calling model's history, about 13,000 extra input tokens per call and again on every
later turn (v0.55.0); ReAct groups one response's tool calls into a single assistant
message (v0.48.0); the three Kimi models that had no price row have one, so an agent
pointed at kimi-k3 no longer runs free in every ledger downstream (v0.50.0); and
usage.by_model[].tokens_cached reports the input the provider served from its cache
(v0.54.0). On behaviour: the hard confirmation gate — an action declared under confirm:
does not run until the person types an exact word, matched against their raw text and
never interpreted by the model (v0.42.0) — spec.prefetch read-only lookups before the
LLM (v0.51.0), seven new declarative integrations, conversational memory that was dead
code until v0.44.0, and a leak closed: an integration handler used to receive the run's
connections and secrets and now gets only the caller's public context (v0.52.1).
Two things to expect at boot, both deliberate and both recorded in runtime.pin:
acuse-programa stays in draft because it needs the glyph extra this image does not
install, and six of the ten packaged agents log a warning and run without
conversational memory because their backends need extras this image does not carry. None
of them fails the boot.
¹ §12.2a sched_ext is implemented (guarded loader + scx_simple, fail-closed, default
off) but its acceptance gate is deferred: Debian's trixie 6.12 kernel ships without
CONFIG_SCHED_CLASS_EXT (confirmed empirically; backports 7.0 has it). Closeable by moving
the kernel baseline — see the schedext design doc §0.1. §12.2b GPU broker is deferred
(no GPU in the VMs; ships with sysext-gpu).
Each phase's acceptance gate builds the image and boots it in QEMU to assert the capability.
phase0-ci runs on every push to main; the per-phase phase{3,4}-* gates run on their
feature branches and via workflow_dispatch.
mkosi and QEMU are Linux-only. On Windows/macOS, build inside a privileged Debian container:
docker run --rm -it --privileged -v "$PWD":/work -w /work debian:trixie bash
# inside the container:
apt-get update && apt-get install -y mkosi qemu-system-x86 git python3 python3-pip
# build the runtime .deb first (see .github/workflows/phase0-ci.yml), then:
PHASE0_MODE=stub mkosi buildCI (GitHub Actions) is the authoritative gate: see .github/workflows/phase0-ci.yml.
For fast iteration without waiting on CI (and without the TCG flakiness of GitHub-hosted runners), reproduce the boot/update gate locally in WSL2 with KVM.
One-time setup (from the Windows host):
wsl --install -d Debian --no-launch
# enable systemd + drvfs metadata, then apply:
wsl -d Debian -u root -- bash -lc "printf '[boot]\nsystemd=true\n\n[automount]\noptions=metadata\n' > /etc/wsl.conf"
wsl --shutdown
# install the same toolset CI uses:
wsl -d Debian -u root -- bash -lc "apt-get update && apt-get install -y mkosi systemd-ukify systemd-boot systemd-boot-efi mtools dosfstools ca-certificates qemu-system-x86 qemu-utils ovmf curl rsync git python3"
# verify KVM is exposed (needs nested virtualization, default on Win11):
wsl -d Debian -u root -- ls -l /dev/kvmIf /dev/kvm is missing, add nestedVirtualization=true under [wsl2] in
%UserProfile%\.wslconfig and wsl --shutdown.
The runtime .deb (rarely changes — depends only on runtime.pin). Fetch the
latest CI build once into dist/ (run on the Windows side, where gh is authed):
gh run download -n astromesh-deb -D distRun the loop (as root in WSL — mkosi needs loop devices). The source of truth
stays on D:\; the harness rsyncs into ~/astromesh-build (native ext4) and builds
there (drvfs can't host a mkosi rootfs build):
wsl -d Debian -u root -- bash /mnt/d/monaccode/astromesh-os/tests/local/dev-loop.sh updateTargets: build (image only) · boot (single-boot + IMMUTABILITY/health assert) ·
update (full A/B v1→v2 gate, default) · inspect (UKI roothash vs on-disk verity
PARTUUIDs) · clean. CI remains the authoritative gate; the local loop is for fast
iteration before push.
runtime.pin pins the exact monaccode/astromesh ref built into the image — prefer a
release tag (e.g. ASTROMESH_REF=v0.28.9) over a floating branch tip. CI checks out that
ref and builds the node .deb from source, so the image is reproducible from it. Bump
deliberately — CI fails if the ref can't be resolved.
