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:
@@ -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/
|
||||
|
||||
@@ -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 |
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 ~1–2 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.
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
@@ -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
@@ -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__":
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user