Files
cubelinux/PLAN-kernel-cubelinux.md
T
luulu 225bbe1f8a Claims that did not survive being checked against the machine
An audit of every document against the running system. The worst one was the front door: the
README said "the kernel running on the workhorse is 6.19.3-cubelinux0.6+ and it holds the
store", and it is not — the box is on GRUB's default entry, the older 6.19.3-cube+, which has
no CUBELINUX configuration at all and no cube(2) to refuse anything. Build #50 did boot it, in
boot -1, and that is what the README now says, with the sha and the way to check.

Also corrected, in the direction of the decision records rather than away from them:

* "the store is sealed at rest throughout" -> 0 of its 69,638 records are sealed, which
  kernel/kill/README.md had said plainly all along. New writes are sealed; the bulk is not.
* "wired into the VFS is not true yet" -> not true *and not planned*: DESIGN-cube-interface
  §2 rejected the mount, so treating it as pending roadmap was the same reversal in prose.
  Same fix at PLAN-kernel-cubelinux.md, which cited the rejected wording as corroboration.
* "1.1-1.8 ms per call" -> replaced with verify-enum-cost.sh, re-run and logged: listing the
  same ten records across a 40x store cost 5.46 ms then 6.24 ms (1.1x, not 1.0x), get 2.45 ->
  2.17 ms, spaces 5.37 -> 4.86 ms. The old figure had no measurement behind it anywhere.
* "Seven gates pass" -> the runner is the authority and the plans no longer carry a copy of
  its list. The count rotted from seven to ten to twenty while the sentence stayed green, and
  one of the ten (verify-efi-boot.sh) was red.
* The boot marker: the repo's deploy/boot_marker.sh writes the coordinate boot:0,0,0, but the
  installed unit runs /home/luulu/.cubelinux-agent/boot_marker.sh, which is a name-tier write
  to cubed-names.sock. The deployed marker is name-tier; the tree's copy is a file nobody runs.
* CUBELinux has run on the workhorse (boot -1, ~80 min, cube_store= set) — the RUNBOOK said
  "never", and its quiesce step still retires a daemon that is no longer the writer.
* Test counts 155/156/157/161 -> 183, measured; three crates the crate map omitted
  (cube-format, cube-kernel, cube-store-seal) added; the README now names both products, since
  the public front door did not disclose the split at all.

PLAN-kernelize-cube.md and PLAN-cube-os-and-cubed.md get banners rather than rewrites: the
first is the rejected mount in its strongest form and is kept as the record of what was
considered, and the second's VFS-shim row and step 4 are struck as withdrawn, not pending.
2026-09-21 17:44:49 -04:00

11 KiB
Raw Blame History

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 — with one word of that claim corrected. The site says the coordinate layer is wired into the VFS, not layered on top. The substance is exactly what this plan delivers: coordinates are the OS's native addressing, not a layer under a path-based filesystem. The literal wording is not, and DESIGN-cube-interface.md §2 rejects the thing that would make it literal — a mount in the core — for four stated reasons. The wording becomes "coordinates are the system's native interface; POSIX is a view at the edge", which is the better claim because it is the one the code can be held to (§3 of that document, and DESIGN-coordinate-surface.md §6 for why the boundary sits where it does).

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 the site's "wired into the VFS" wording is not a pending item — the mount it describes was decided against in DESIGN-cube-interface.md §2, so the sentence changes rather than the architecture. 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

In progress. The tree lives at /home/CUBE-OS/kernel/CUBELinux (git-ignored by the parent repo; the harness around it is tracked), cloned from upstream v6.19.3 — never from CUBED's tree, which stays frozen. Steps 1, 2, and the first half of 5 are done:

Step State
1. Establish the tree, named CUBELinux.0.1 ✅ vCUBELinux.0.1 tagged; make kernelrelease → CUBELinux.0.1, base 6.19.3 still visible in make kernelversion
2. Prove the toolchain ✅ make LLVM=1 bzImage builds with CONFIG_RUST=y; six toolchain-compat changes committed (see kernel/README.md)
3. A minimal Rust kernel module builds in-tree ✅ drivers/cube/ — a Rust misc device, CONFIG_CUBELINUX_STORE=y
4. Read path: the kernel decodes the store's records ✅ CUBELinux.0.2 reads the pinned image off a block device and its digest matches userspace exactly, on both a 4 KiB curated volume and the 8.4 MB snapshot (35,318 records)
5. Boot in QEMU ✅ boots, brings up virtio-blk, and the kernel's own read of /dev/vda — through /dev/cubelinux — is compared against userspace by the gate

So the milestone reached is: the kernel reads the CUBE store from raw blocks and returns the same records the userspace reader does, byte for byte. What is not there is any write, any coordinate interface, and any kernel-side store: /dev/cubelinux is a reader, and the write-authority decision in §4 below stays open on purpose. kernel/README.md states the same boundary.

The write path is under construction against §4's decision, and the kernel now writes:

✅ Replay the kernel reads the image and the log that follows it, newest write per coordinate wins, removals are removals — digest-identical to a userspace checkpoint (kernel/verify-log-replay.sh)
✅ Append a mutation through /dev/cubelinux is written and fsynced before it is accepted; userspace can read the kernel's own log and fold it to the same store, and every acknowledged write survives a SIGKILL of the VM (kernel/verify-kernel-append.sh)
✅ Checkpoint in the kernel sync folds the log into the spare slot and flips the control block; the image it writes is byte-identical to the userspace one. The kernel no longer depends on a userspace fold to reclaim its log
✅ Torn tail a corrupted entry is discarded, what preceded it survives, and the next append overwrites the tear rather than burying it — a real bug in both implementations, found by building the gate
✅ cube(2) CUBELinux.0.6: number 548 — put/get/del/sync and the cursor walk (ENUM/SPACES, versioned by the size of its argument block); the store it produces is byte-identical to userspace's
✅ A front-end over cube(2) the socket clients keep working through the kernel (kernel/verify-frontend.sh) — the last piece before the demotion
✅ Booting the box's config the kernel is built with the machine's own working config (/boot/config-6.19.3-cube+ + CONFIG_CUBELINUX_STORE=y) — the defconfig this work started from has no NVMe driver and could not mount the box's root. The boot chain is rehearsed in a VM (kernel/verify-nvme-boot.sh), and build #50 booted the workhorse with cube_store=/var/lib/cubelinux/store.img; the box gates were green on it
🟡 The daemon's demotion the sequence is rehearsed in a VM, including the hazard it avoids (kernel/verify-handover-rehearsal.sh, RUNBOOK-write-authority-cutover.md). This is now a decision still to be taken rather than a step blocked on missing pieces: the syscall, the front-end and the hardware boot are all done

The gates are not listed here, and that is deliberate. This section used to carry a seven-row table and the sentence "seven gates pass on CUBELinux.0.6". By 2026-09-21 the runner named twenty-one gates and one of them (verify-efi-boot.sh) was red — so the plan was asserting four things that were not true, and a reader following it would have believed a green board that did not exist. A duplicated list is a second mechanism beside the real one; that is how it rotted.

kernel/run-all-gates.sh is the authority. It runs every gate, names the claim each one makes, and reports a gate it cannot run as skipped with the reason rather than as a pass. Run it, and that output is the state of this plan — with one caveat worth knowing before you read it: the box-only gates need the CUBE-OS kernel booted here, because GRUB's default entry is the old 6.19.3-cube+ and a plain reboot lands on that. A gate is a claim, and the image reader is one gate over three fixtures rather than three gates.

  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. The write path: decided, and what is still open

  • ✅ The kernel write path's format — decided: append a log, fold it into the pinned image at a checkpoint, and keep the image canonical. DESIGN-cubelinux-write-path.md records the decision, the log and checkpoint design, the differential/crash/torn-tail gates it will be judged by, and the one threshold that would reopen it (tens of GB, with throughput as the binding constraint — and even then as a second backend behind the same Store contract, not as a replacement format).
  • ✅ Format v2 shipped with it: the image's byte extent and record count in the header, because v1 walked until it met zeros and a log sits right after the image. v1 images still read; the kernel reader handles both, verified by the gate on each.
  • ✅ The shape of the coordinate interface — decided: a coordinate syscall family (cube(2), one number with opcodes, operations identical to the command language's verbs). POSIX is a view at the edge, not a mount in the core; DESIGN-cube-interface.md records the reasoning, the four reasons a mountable filesystem was rejected, and the one honest edit the website's "wired into the VFS" wording needs. A consequence worth noting: the minimal write operation the write path needs is CUBE_PUT, so that work is not scaffolding.
  • ⬜ 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.