finish: README, the kernel decision, and the spec reconciled

Part one of the two-part plan, closing out the userspace substrate before the
kernel work:

- PLAN-kernel-cubelinux.md: the decision (the kernel owns the store; coordinates
  are resolved in the kernel; the block driver is persistence plumbing; POSIX is
  an edge view) plus the two-part plan and the one design fork left for the
  write-authority phase.
- README.md: what CUBE-OS is, the crate map, quickstart, the release gates, and
  the "claims not yet true" list (kernel not coordinate-native yet; installed
  kernel is CUBED's).
- Superseded banners on the pre-split docs (PLAN-os-layer.md,
  INTEGRATION-cube-agent.md, PLAN-debugging.md, cube_harness.py) and the fixed
  stale rows (DESIGN-coordinate-layer.md, a cube-header comment).
- cube_ctl.py: the `spawn` subcommand and CubeSpawner, which shelled the deleted
  cube-spawn crate, now refuse with a clear message instead of pretending.

Release checklist green: 157 tests, 0 clippy warnings, image verifies (snapshot
8,399,506 B; live 16,537,516 B), cube-core cross-builds for thumbv7em-none-eabihf,
durability harness PASS, and the name-tier path end to end. Tagged cubelinux-0.1.0.
This commit is contained in:
luulu
2026-09-18 19:25:30 -04:00
parent 5b1ec1e9a9
commit ad648b4ea6
10 changed files with 213 additions and 15 deletions
+1
View File
@@ -23,3 +23,4 @@ html/files/
# "soapp"). It is a reflection, not source — edits here never reach the site, and
# the real source of truth for what is live is the remote host itself.
site-mirror/
/kernel/
+1 -1
View File
@@ -212,7 +212,7 @@ pub trait Resolve {
| `cube-core` | `Coord`, `Curve`, `Portal`, `Resolve`. Pure logic. | `no_std` |
| `cube-store` | storage trait + `mem` / `file` / `raw-block` backends | std |
| `cube-index` | sparse index over the curve; region/portal catalogue | std |
| `cube-api` | the surface a program actually calls | std |
| `cube-command` | the command language; the surface a program actually calls | std |
| `cube-bench` | decides §1 on real hardware; keeps it reproducible | std |
| `cube-cli` | operator tooling; makes the thing pokeable by hand | std |
+4
View File
@@ -1,4 +1,8 @@
# CUBE <-> Local LLM Agent Integration Contract
> **Superseded.** This document predates the two-product split. The path/POSIX/name tier it
> describes left CUBE OS and belongs to CUBED (`/home/CUBEdb`); CUBE OS is the coordinate
> substrate only. See `PLAN-cube-os-and-cubed.md` and `README.md` for what is true now.
Status: 2026-08-09 (rev 2026-08-10: +cube-index crate, mindex-* CLI, AdjacencyIndex fast-path; +cube-api crate, native one-type binding surface; +cube-daemon crate (cubed), Unix-socket service over cube-api — the agent's native endgame). Owner: CUBELinux build. Enforced by code, not trust.
+4
View File
@@ -1,4 +1,8 @@
# Debugging Options for CUBELinux Crates
> **Superseded.** This document predates the two-product split. The path/POSIX/name tier it
> describes left CUBE OS and belongs to CUBED (`/home/CUBEdb`); CUBE OS is the coordinate
> substrate only. See `PLAN-cube-os-and-cubed.md` and `README.md` for what is true now.
Living spec. As we build each crate, it gets a `debug` Cargo feature that gates
runtime observability and expensive invariant checks. Off by default → zero
+98
View File
@@ -0,0 +1,98 @@
# PLAN — CUBELinux.0.1: the kernel build
Status: 2026-09-18. This is the plan the kernel work points at, and it begins with the one
decision the previous work was waiting on.
## 1. The decision
**The kernel owns the store.**
* Records are found by **coordinate in the kernel** — a native coordinate interface, not a
path, and not a filesystem bolted on top of the store.
* **The block driver is persistence plumbing.** It is how the kernel writes and reads the
pinned image on a partition, the way a filesystem writes its own superblock and inodes.
It is not an interface handed to userspace.
* **The kernel writes.** One writer, owned by the kernel. A userspace daemon that holds the
canonical store is a privilege inversion and a single point of failure; that authority
moves into the kernel.
* **POSIX is an edge compatibility view, or absent.** Where a path is wanted, the mapping
(name → coordinate) lives at the edge — the `cube-names` pattern, generalized to paths —
never inside the store and never in the kernel's coordinate interface.
This is the only arrangement consistent with the published claim: the coordinate layer is
*wired into the VFS, not layered on top*, and there is *no translation step* in the OS.
### What this means for the userspace we built
`cubed`'s write authority and its in-memory copy of the image are superseded on the target
system. It becomes a front-end over the kernel's coordinate interface (so the CLI, the
translator and the guest bridge keep working with a one-line backing change), or an
offline-only tool for cold images. The write-ahead log was a userspace durability device;
the kernel gets its own write path (see §5), and the pinned image remains the one format
every reader understands.
### Naming
The kernel is **CUBELinux**. Releases are `CUBELinux.0.1`, `CUBELinux.0.2`, …;
`uname -r` reads `CUBELinux.0.1`. The base is Linux 6.19.3, the same base as the installed
`6.19.3-cube+`, so the Rust toolchain and version already match.
## 2. Part one — finish and commit the crates
Userspace CUBE-OS is left in a finished, tagged state:
1. Record this decision (this document).
2. Reconcile the published spec with the code: CZYX is the *spelling of a subregion*, the
name tier lives *at the edge*, and "wired into the VFS" is the roadmap, not yet true.
The "claims not yet true" list lives in `README.md`.
3. A top-level `README.md`: crate map, the boundary, how to run each piece, the gates.
4. Sweep stale references to the removed crates (`cube-api`, `cube-fs`, `cube-os`,
`cube-plane`, the platform crates) from the docs and scripts that still name them.
5. Release checklist: `cargo build/test/clippy --workspace` (0 warnings), `cube-image
verify` on the snapshot and the live store, the `thumbv7em-none-eabihf` cross-build,
`cube_duratest.py`, and `deploy/verify-name-tier.sh`.
6. Commit and tag `cubelinux-0.1.0`.
**Gate:** clean tree, 0 warnings, every gate green, tagged.
## 3. Part two — start the CUBELinux kernel build
The tree lives at `/home/CUBE-OS/kernel/CUBELinux` (git-ignored by the parent repo), cloned
from upstream `v6.19.3` — never from CUBED's tree, which stays frozen.
1. **Establish the tree.** Fresh 6.19.3, named CUBELinux, release `CUBELinux.0.1`, a
**minimal VM config** (`allnoconfig` + `RUST` + block + virtio + our module) — not the
304 KB hardware config CUBED carries. Keeps the tree ~12 GB against the 11 GB free.
2. **Prove the toolchain.** rustc 1.100.0-nightly, clang 19.1.7, bindgen are present; put
the LLVM binutils on `PATH`. Gate: `make LLVM=1 bzImage` produces a bootable image.
3. **A minimal Rust kernel module** builds in-tree, proving the Rust pipeline end to end.
4. **Read path.** Port the pinned-image record reader into the kernel. `cube-core` and
`cube-store-raw` are `no_std`-friendly already, so the format logic is reusable. Gate:
the kernel reads a store image from a virtual block device and returns the same records
a userspace `cube-image` read does.
5. **Boot in QEMU first.** Never the workhorse. A minimal kernel plus a virtual disk
holding a store image; verify the read gate inside the VM.
**Gate:** `CUBELinux.0.1` boots in QEMU and decodes a store image from blocks,
record-for-record identical to userspace.
## 4. Not yet decided, and deliberately deferred
* **The kernel write path's format.** The pinned image is a checkpoint format (a sorted
blob, rewritten whole and renamed). The kernel cannot rewrite it per write — measured
~458 writes/s doing that in userspace. So the kernel needs either a port of the
log-then-fold story, or a mutable on-disk format with the pinned image kept as the frozen
export. This belongs to the write-authority phase, *after* the read path boots, and is
the one design fork left to take.
* **The shape of the coordinate interface** — syscalls, a mountable coordinate filesystem,
or both.
* **The daemon's retirement** — front-end over the kernel, or offline-only.
## 5. Constraints that stay true throughout
* Do not modify CUBED (`/home/CUBEdb`) or its kernel tree.
* Do not boot an experimental kernel on the workhorse until it has passed in QEMU.
* The pinned image format is the single on-disk contract across kernel, userspace, the
converter, and CUBED.
* The name/path tier stays at the edge; the kernel's coordinate interface never interprets
a name.
+4
View File
@@ -1,4 +1,8 @@
# Plan — the OS layer over Tree A
> **Superseded.** This document predates the two-product split. The path/POSIX/name tier it
> describes left CUBE OS and belongs to CUBED (`/home/CUBEdb`); CUBE OS is the coordinate
> substrate only. See `PLAN-cube-os-and-cubed.md` and `README.md` for what is true now.
Status: **shipped** (see §7 for what landed and what it cost) · written before the
control plane was implemented, on purpose
+87
View File
@@ -0,0 +1,87 @@
# CUBE-OS
The coordinate substrate of CUBELinux: a store addressed by coordinate, a command language
over it, and the boundary that turns names into coordinates at the edge. Everything here is
userspace Rust; the kernel half is `PLAN-kernel-cubelinux.md`.
```text
coordinate substrate (§5) the boundary the edge
cube-core cube-store cube-header cube-command cube-daemon cube-names
cube-index cube-crypt cube-store-raw cube-client cube-cli (name -> coordinate)
```
## The shape of it
* **A coordinate** is `SpaceId` (256-bit) + `Point` (three `u64`). Nothing here is addressed
by name or path. `czyx:c,z,y,x` is the published four-axis *spelling* of a subregion, not
a second model.
* **The language** (`cube-command`) is one implementation shared by every front-end:
`put`, `get`, `del`, `cell put|get|del`, `range`, `list`, `spaces`, `hdr`, `link`, `out`,
`follow`, `keys`, `seal`, `open`, `czyx`, `checkpoint`. A value is text, or `hex:<digits>`
for bytes.
* **The daemon** (`cubed`) holds one store and serves the language over a Unix socket; a
mutation is acknowledged only once it is durable in the write-ahead log. One writer, one
store — that is why a daemon exists at all.
* **The client** (`cube-client`) is the other half of the socket, and `DaemonStore` presents
the daemon's store through the `Store` contract.
* **The name tier** (`cube-names`) accepts the name-addressed protocol the machine's older
services speak, maps it with `Coord::named`, and runs the command against the daemon. It
is the edge, not the substrate — the prototype of the POSIX compatibility view the kernel
plan describes.
## Quickstart
```bash
cargo build --release --workspace
# serve a store (write-ahead log beside the image is the default)
./target/release/cubed --store /tmp/demo.store --socket /tmp/demo.sock
# talk to it — the same verbs a local store runs
./target/release/cubecli --socket /tmp/demo.sock put root:1,2,3 hello
./target/release/cubecli --socket /tmp/demo.sock get root:1,2,3
./target/release/cubecli --socket /tmp/demo.sock put czyx:2,3,4,5 hex:001bff
./target/release/cubecli --socket /tmp/demo.sock list root
```
## The gates (run before calling it done)
```bash
cargo test --release --workspace # 157 tests
cargo clippy --release --workspace --all-targets # 0 warnings
./target/release/cube-image verify /root/workspace/cube-snapshot.img
cargo build --release -p cube-core --target thumbv7em-none-eabihf
python3 cube_duratest.py # acknowledged writes survive SIGKILL
bash deploy/verify-name-tier.sh # the full name-tier path, on /tmp sockets
```
## The crate map
| Crate | Role |
|---|---|
| `cube-core` | `Coord`, `SpaceId`, `Point`, curves, `Czyx`, `WordFlags`/`TriWord`/`HeaderFlags` |
| `cube-store` | the `Store` contract, `MemStore`, `FileBackedStore`, the write-ahead log |
| `cube-store-raw` | the pinned 24-byte-key image format |
| `cube-header` | `CubeHeader`, `HeaderStore`, association edges |
| `cube-index` | `AdjacencyIndex`, portals |
| `cube-crypt` | sealing, the OS keystore |
| `cube-command` | the command language, one implementation for CLI and daemon |
| `cube-daemon` | `cubed` — one store, served over a socket |
| `cube-client` | the client half of the socket; `DaemonStore` |
| `cube-cli` | `cubecli` — the operator CLI, local or `--socket` |
| `cube-names` | the name tier at the edge (name → coordinate) |
| `cube-image` | reads/writes/verifies the pinned image |
| `cube-bench` | block-read benchmarks, the on-ramp for the kernel read path |
## Claims not yet true
The website says the coordinate layer is *wired into the VFS* and that the OS *stores
itself*. That is the roadmap, and it is not yet shipped:
* The installed kernel (`6.19.3-cube+`) is CUBED's; it contains no CUBE-OS code.
* There is no kernel coordinate interface yet — only the userspace daemon.
* "The OS stores itself" is a boot marker written by a client through the name tier, not
the kernel storing its own records.
These become true in `PLAN-kernel-cubelinux.md`, part two. The code and the crates here are
the substrate that work builds on, and they are done.
+1 -1
View File
@@ -692,7 +692,7 @@ impl<'a, C: Curve> HeaderStore<'a, C> {
// --- read-only helpers ------------------------------------------------------
//
// These take `&dyn Store`, so a *reader* never needs a mutable borrow. That
// matters for the layers that walk the graph: `cube-code`'s VM runs a program by
// matters for the layers that walk the graph: a VM runs a program by
// reading cells and following their edges, and a VM that can only borrow the
// store mutably forces callers to clone the store or serialize readers against
// writers for no reason.
+10 -13
View File
@@ -196,7 +196,12 @@ class DaemonClient:
# ---------------------------------------------------------------------------
class CubeSpawner:
"""Spins up named cubes via the `cube-spawn` crate.
"""REMOVED from CUBE OS: `cube-spawn` and the VM/spawn tier moved to CUBED.
Kept only so the reference is explicit; the `spawn` command refuses with
this same message.
Spins up named cubes via the `cube-spawn` crate.
Currently shells `cargo run -p cube-spawn -- <args>` as a subprocess.
Long-term: replace with a pyo3-based direct call once cube-spawn exposes
@@ -530,8 +535,8 @@ def main() -> None:
p.add_argument("namespace")
p.add_argument("--socket", default=DEFAULT_SOCKET)
# spawn (via cube-spawn crate)
p = sub.add_parser("spawn", help="spawn a named cube")
# spawn (via cube-spawn crate) — REMOVED from CUBE OS; see CUBED.
p = sub.add_parser("spawn", help="spawn a named cube (removed: lives in CUBED)")
p.add_argument("name")
p.add_argument("--curve", default="morton")
p.add_argument("--backend", default="file")
@@ -564,16 +569,8 @@ def main() -> None:
result = c.list(namespace=args.namespace)
print(json.dumps(result.get("entries", []), indent=2))
elif args.command == "spawn":
spawner = CubeSpawner()
result = spawner.spawn(
name=args.name,
curve=args.curve,
backend=args.backend,
store_path=args.store,
with_daemon=args.daemon,
socket_path=args.socket_path,
)
print(json.dumps(result, indent=2))
print("spawn removed from CUBE OS: the VM/spawn tier lives in CUBED", file=sys.stderr)
sys.exit(2)
if __name__ == "__main__":
+3
View File
@@ -1,5 +1,8 @@
#!/usr/bin/env python3
"""
SUPERSEDED: cube-spawn and the special-use cubes this drove left CUBE OS
(with the path/name tier); they live in CUBED. See README.md. Kept for reference.
cube_harness.py use-case harness for CUBELinux special-use cubes.
Provides: