docs/GRAPH.md
back to source
# NumericalOS — pure graph-driven Linux userspace
NumericalOS is not “systemd with a graph UI.” The **runtime configuration is
only** the content-hashed export of a typed unit/phase/health graph. There are
no unit files on the target, no `/etc/systemd`, and no free-form shell rc that
defines boot order outside the export.
## What “pure graph” means here
| Claim | Meaning |
|---|---|
| Graph is source of truth | Boot order, units, health, floor applets live in `numos.distro` / seed / ops registry |
| Export is the wire | `numos.state` is the sole PID-1 input (plus floor binary + bootstrap) |
| Hash is the seal | `C <sha256>` — hand edits fail closed at boot |
| Profiles are compositions | `self-init` vs `fleet` select different subgraphs, not different codebases |
| Floor is graph-resolved | Packers install `numos-floor` from URL+sha256 in `distro.floor.json` |
What is **not** pure graph (named residuals):
- The multi-call floor **implementation** may still be a BusyBox build (GPL); product identity is `numos-floor`.
- The **kernel** is third-party and graph-**pinned** (`KernelProvider` / `distro.kernel.json`), not built by NumericalOS. ASEC residual: package sha256 pin optional; Secure Boot chain is Tarski for Spec 1.
- **Live** IntrikataTopology ops catalogue is optional (fleet `include_op_units`); offline self-init seeds the graph in-repo.
## Quartet mapping (export product)
| Layer | Node kinds | Role at boot |
|---|---|---|
| **META** | `DistroProfile`, `FloorProvider`, `KernelProvider` | Product, floor URL/sha256, third-party kernel pin |
| **GENESIS** | `BootPhase` (+ media kernel edge) | Ordinal walk; ISO needs graph kernel pin |
| **MGS** | `OSUnit` | oneshot / longrun; `requires` / `after` DAG |
| **SHADOW** | `HealthPredicate` | Steady-state probes; local actions |
ASEC-style self-heal in Spec 1 is **local**: restart policies + health
`local_action` (e.g. `degrade-node`). KernelProvider carries an **ASEC residual
list** (unsigned package, missing arches) — named, not silent-defaulted.
Full swarm orchestration is Spec 2+.
## Profiles
### `self-init` (offline complete)
Phases: `mount` → `identity` → `complete` (hold longrun).
Units: `mount-proc`, `mount-sys`, `mount-dev`, `identity`, `hold`.
Health: `hold-alive`.
**Observed:** x86_64 QEMU kernel+initrd and hybrid ISO serial →
`boot complete degraded=0`.
### `fleet` (topology node)
Phases: original infra (mount/net/clock/identity/join).
Expect **PASS-degraded** on bare QEMU without eth0/ntpd/coordinator.
## Developer commands
```bash
# Inspect profiles
py -3 -m numos.distro list
py -3 -m numos.distro --profile self-init summary
py -3 -m numos.distro --profile self-init graph # nodes + edges JSON
py -3 -m numos.distro --profile self-init mermaid # flowchart
py -3 -m numos.distro --profile self-init floor --arch x86_64
py -3 -m numos.distro --profile self-init kernel --arch x86_64
# Export boot artifact + graph sidecars
py -3 -m numos.export_state --profile self-init --seed-only --out dist
# writes: numos.state, numos.state.json, distro.floor.json, distro.kernel.json,
# distro.profile.json, distro.graph.json, distro.graph.mmd
```
## Runtime chain (still graph → text → shell)
1. **Export** graph → `numos.state` (+ JSON/graph sidecars for tools).
2. **Pack** initramfs/ISO reads floor from graph manifest; installs state at
`/etc/numos.state`.
3. **Bootstrap** verifies hashes; execs `numinit`.
4. **numinit** walks phases/units from the state file only.
Changing boot behavior = change the graph profile (or ops registry), re-export,
repack, re-verify. Never hand-edit `numos.state`.
## Wire format
See [the state format](/docs/format/) on the site and `docs/PRINCIPLES.md`.
Seven record types: `V C A P U R X`. Field positions are a wire contract for the
shell floor.
## Related
- `numos/distro.py` — profile compositions
- `numos/seed.py` — fleet infra + arch targets
- `numos/export_state.py` — deterministic exporter
- `docs/observations/` — boot evidence (scoped)
- Design: `docs/superpowers/specs/2026-08-04-numericalos-design.md` §4–5