Two documents in this tree present themselves as current and describe CUBELINUX-2: CUBELinux-whitepaper-final-draft.txt (added 2026-09-06, untouched since, 0% CUBE-OS — no #548, no cube(2), no v3, no build #50, none of the 183 tests, and every /home/CUBELinux/... path it cites as authority is ENOENT) and CUBE-FUSE-project.txt. Both get banners naming what is stale, rather than rewrites: the whitepaper's coordinate design is still the substrate's design, and the FUSE review is the record of the edge view working — which is worth having, because DESIGN-coordinate-interface §2.4 blesses that view and §6 explains why its readdir is fine there and disqualifying in the core. STATUS-packages.md: the TriWord/TriEnc row said "deliberately not ported" and the crate is here (cube-core/src/wordflags.rs, re-exported); §3.3's heading said the same and is now "ported as a reader, not as the body", which is the narrower claim the section actually argues. The cube-os row linked two files that no longer exist, the counts are 183 now rather than 156/161, and the mount/inode rows are marked as what they are: the ledger of a period when one tree carried every package. Two citations are corrected rather than quietly left: PLAN-cube-os-and-cubed.md attributed a sentence to "whitepaper §6" that the whitepaper does not contain ("third impl" has zero occurrences in it) and called FUSE's format-proof role "Whitepaper §7.1", a section about the physical workhorse — "format-proof" appears zero times there, and the phrase is from CUBE-FUSE-project.txt:229. Invented attributions are worse than missing ones: they make a sound argument look sourced.
18 KiB
Package status — Tree A against CUBELinux.pdf
Status: all five PDF packages are implemented in Tree A · 2026-08 · 161 tests green then; 183 measured today
Read this first (2026-09-18). The tables below are the ledger of the period when one tree carried every package. That is no longer the shape of the project: CUBE OS (
/home/CUBE-OS) is now the coordinate substrate — whitepaper §5's crate set — and CUBED (/home/CUBEdb) is the standalone CUBE where namespaces, paths, the VM, the ball index and the FUSE mount live. Several crates named below (cube-fs,cube-os,cube-plane,cube-fuse-proxy,cube-code,cube-trace,cube-dbt,cube-ai, the platform services) have left CUBE OS; the per-crate decision table is inPLAN-cube-os-and-cubed.md§4 and the split itself inREVIEW-two-cubes.md.Two rows have also moved on since this ledger was written: the daemon no longer serves a namespace API but the command language over coordinates, and
cube-apiis deleted (CUTOVER-language-protocol.md). Current state: 183 tests green in CUBE OS (measured 2026-09-21 withcargo test --release --workspace; the 156 and 161 above are this ledger's period), no clippy warnings; the daemon cutover on the live machine is recorded inCUTOVER-language-protocol.md.Three rows below are also wrong as statements of CUBE OS today, corrected here rather than silently:
TriWord/TriEncARE ported (crates/cube-core/src/wordflags.rs, re-exported fromlib.rs) — the ❌ at §3.3 and the row at :40 are stale, andPLAN-cube-os-and-cubed.md§3 has them as built. Thecube-osrow at :42 linkscrates/cube-os/src/bind.rsandos.rs, and neither file exists —cube-osleft this tree. And thecubefsmount row at :37, plus the "inode generation scheme" at :203, describe a mount and its inode machinery as CUBE OS backlog;DESIGN-cube-interface.md§2 rejected a mount in the core andDESIGN-coordinate-surface.md§6 says why the inode machinery is not wanted back. This file is the ledger of the period when one tree carried every package; it is not a current status, which is what its own banner above already says.
This document is the completion ledger for the source specification. The PDF (66 pp, a transcript rather than a spec) names five packages, a tri-channel word encoding, and a header/flag scheme. Each row below says where that lands in Tree A, and — where Tree A deliberately departs — why.
The short version: Tree A implements every package, and disagrees with the specification in exactly three places, each for a measured reason. The disagreements are recorded as decisions, not gaps.
1. Package-by-package
| PDF package | What the PDF asks for | Tree A | State |
|---|---|---|---|
1. cubecoords |
Core primitives, Czyx + pack/unpack to u32, null vs user space, no dependencies |
cube-core — SpaceId (256-bit) + Point (three u64) + Coord, Curve (Morton/Hilbert), portal, Region |
✅ implemented, coordinate model width differs by design (§3) |
2. cubestore |
A generic cube abstraction over any CubeBackend: put/get/delete by coordinate, CubeHeader, CubeRecord, associate(src,dst), "all records linked to X" |
cube-store (Store trait, MemStore, FileBackedStore, Region queries), cube-header (CubeHeader + HeaderStore + edges in NULL_SPACE), cube-index (adjacency/portal index) |
✅ implemented |
3. cubefs |
Mount the cube as a namespace; map axes to directories/files; Null cubes for ACLs, xattrs, journaling | cube-fuse-proxy (FUSE mount), cube-cli, cube-daemon + cube-client (shared store over a socket) |
⚠️ partial — see §4. Gap analysis in progress |
4. cubevm / cubecode |
Code and AI artifacts as records; call graphs, dependency edges, variants, version history via links; a runtime that walks links to dispatch functions | cube-code (opcode codec, CodeCell, deterministic Vm, edges as the call graph, ball index, trace/golden artifacts), cube-trace (capture head), cube-dbt (translation rules → code cache), cube-ai (classify → suggest → feed the translator) |
✅ implemented |
5. cubecrypt |
Null cubes as environment settings; key material in cells; record-level selectors; audited crypto only; access logs and tamper-evident metadata in separate null ranges | cube-crypt — CubeEnv, KeySlot, sealed envelopes (AES-256-GCM / ChaCha20-Poly1305 / AES-XTS), keyinit (OS keystore), AccessLog, HMAC hello auth |
✅ implemented |
Tri-channel word (TriWord/TriEnc) |
Pack 6 ASCII chars + 4 control bits into 64 bits | cube-core::wordflags — wordflags.rs keeps the original layout and TriEnc::pack_6 is the PDF's packing |
✅ ported (§3.3 — this row said "deliberately not ported" and was wrong; the crate is here and re-exported from lib.rs) |
| Header/flag scheme | Titles, types, dates, sizes, permissions, associations, counters as Null-space flag bytes or a typed header struct | cube-header::CubeHeader — fixed 26 bytes: kind, size, created_at, links, visibility, 16 flag bits, 8 meta bytes; Behavior descriptors in the out-of-band half |
✅ implemented as the typed struct the PDF's Rust sketch prefers (§3.2) |
| The layer the PDF implies but never names | Something that makes packages 3–5 interoperate | cube-os — bind crossed between path/coordinate/code/ciphertext; os was a store, an identity and an environment where every operation is admitted before it is applied and recorded whether or not it was |
✅ was implemented — and cube-os has left this tree (2026-09-21: neither linked path exists any more; see the banner above) |
2. Reserved spaces (the "Null cubes")
The PDF reserves coordinate ranges. Tree A reserves whole 256-bit spaces, each owned by the layer that needs it:
0xFF… association edges cube-header::NULL_SPACE
0xFE… portal descriptors cube-index::PORTAL_SPACE
0xFD… OS keystore cube-crypt::KEYSTORE_SPACE
0xFC… captured trace events cube-trace::TRACE_SPACE
0xFB… code + run artifacts cube-code::CODE_SPACE (bands on the Y axis)
0xFA… stored index structures cube-code::INDEX_SPACE
0xF9… ordinal registry cube-fs::REGISTRY_SPACE
per-space header space cube_header::null_space_for(space)
per-domain registry cube-fs::Registry::for_domain(space)
The reservation convention is a rule, not a list: a reserved space is an
all-equal-byte space in 0xF0..=0xFF (cube-fs::is_reserved_space). That is what
lets a namespace listing skip the control plane without a hard-coded table that
drifts every time a layer is added, and it is why a user space should not be
chosen from that range.
Which space is C?
ordinal 0 reserved, never names a space (the PDF's "0 = Null")
ordinal 1 the fixed root: SpaceId::from_name("cube/root") — public by design
ordinal 2.. allocated through a registry, in a space of the registry's choosing
A space id is a capability, so ordinals are labels, not identities: C=2
resolves through a registry record to a SpaceId, exactly as a hostname resolves
through DNS. If C were the identity, spaces would be enumerable and the
capability property would be gone — the same measurement that ruled out a 32-bit
keyspace. Ordinals also are not invariant under copying a store, and a bare 1 in
a path already means the space 0x…01, so ordinals are spelled c1, c2, … in
paths.
The root is derived from a name, hence publicly computable. That is deliberate: the
OS must find its own space at boot with no prior secret. A boot-discoverable root
and an unguessable tenant space are different jobs. Isolation for the rest comes
from where the registry lives: Registry::global is the OS's own table,
Registry::for_domain derives a private one from a domain's SpaceId, so reading
a tenant's mounts requires already holding that tenant's capability.
CODE_SPACE carries its bands as addresses, not as separate spaces:
y = 0 Kernel · 1 Effect · 2 DbtRule · 3 DbtCache · 4 Trace · 5 Golden · 6 BlockTrace. That is the shape a 192-bit address space is for — one reserved
space can hold a structured namespace without spending a reservation per
feature.
3. The three deliberate departures
3.1 Coordinate width: Point is u64 × 3, not u8 × 4
The PDF's Czyx is four 8-bit axes, giving a 32-bit keyspace. Tree A uses a
256-bit SpaceId plus three 64-bit axes: 2^192 points per space.
Measured reason (see REVIEW-cubelinux-pdf.md §2 and cube-core's module docs):
a 32-bit keyspace holds ~4.23 × 10^9 cells and is exhaustively enumerable. A
coordinate in this system is a capability — knowing it is the authorisation —
and a capability you can enumerate by brute force is not one. 256 bits of space
is unguessable; 192 bits of point is unenumerable.
Everything else in the spec is separable from coordinate width, which is why Packages 2–5 ported onto the wider model without changing what they mean.
3.2 Headers carry a kind byte, not title/type strings
The PDF's header sketch (from the 2006 notes) has free-text title, doc_type,
owner. That is a name space bolted onto a system whose entire claim is that a
position in space resolves to bytes. Tree A stores a typed EntityKind byte
instead:
0 Data 1 Memory 2 Session 3 Project 4 Edge 5 Fn 6 Kernel 7 Layer
8 Checkpoint 9 Variant 10 Trace 11 Golden 12 IndexNode 0x80|d NullSpace(d)
Kinds 5..=12 are the PDF's Package 4 types, added additively in a previously
unused range — the 26-byte layout never changed. Naming belongs to a namespace
layer (a cubefs path, a project record, an association), where the PDF's own
Package 3 already puts it.
3.3 Tri-channel word encoding: ported as a reader, not as the body
Corrected 2026-09-21: this heading read "not ported", which was false. TriWord and TriEnc
are implemented in crates/cube-core/src/wordflags.rs and re-exported from lib.rs;
PLAN-cube-os-and-cubed.md §3 lists them as built. What the section below argues is the narrower
and still-good point — that the encoding is not used as the store's record framing, because the
density arithmetic does not pay off against this store's actual record shape.
TriWord packs 6 ASCII characters plus 4 control bits into 64 bits to trade CPU
for I/O density. Measured against the store's actual record shape, it raises
stored size by ~25% on this workload (reflated density regression, recorded
during the A/B comparison) — the encoding pays off only when a backend is
byte-addressed at 6-byte granularity, which cube-store is not. The claim
("trading CPU for I/O/space efficiency") is a hypothesis about a KV store's
block layout, and on this one it loses.
Revisit if a byte-addressed backend is ever the target; it is an encoding choice, not a foundation, so nothing else depends on the decision.
4. What is genuinely not done
| Item | Where it stands |
|---|---|
| Package 3 control plane | Shipped: volume metadata (label + layout version), grants (the authority primitive, including OWN as a grant so a record needs no owner field), extended attributes mirrored in their own space, and the journal band, which cube-os uses for its decision trail. Not implemented: POSIX mode/uid/gid as views over grants, a general inode-generation scheme, and the ring/wrap semantics a long-lived journal wants. |
| Sharded multi-writer MVCC store | The sibling tree has an MvwBackend (shards, per-shard WAL, LSM-lite compaction). Not ported: it is a storage engine, not a coordinate-layer feature, and Tree A's durability story is already FileBackedStore + the pinned raw-block format (cube-store-raw) + the daemon. Porting it would mean a second, competing durability model. Decide deliberately, not by drift. |
OS integration (cubesys) |
Explicitly the next phase, and deliberately after this ledger: the OS layer should be built on a frozen substrate. |
| Kernel work | PLAN-kernelize-cube.md tracks it; the running 6.19.3-cube+ kernel contains no CUBE code yet. Two format questions belong with it: an explicit record count or terminator in the raw header (the padding class is fixed by a reader rule, but the format still cannot say how many records it holds), and whether the kernel reads the store directly or through cubed. |
| Shared-store access | Shipped as the daemon boundary: cubed holds one store and serves the command language over a Unix socket, and cube_client::DaemonStore presents that same store through the Store contract, so a mount and the system layer address one store instead of each holding a private copy. The old raw_* coordinate operations are gone with the namespace API they sat under — one protocol, not two. What is not there: change notification, so a client learns about another process's write only when it asks again. |
4.1 The Package 3 control plane: what shipped, and where
The PDF says "use Null cubes/rows for ACLs, extended attributes, journaling, volume metadata" but not which one holds which. Two derivation rules cover it, and a namespace listing needs to recognise both:
header partition null_space_for(space) one 26-byte header per record
metadata plane meta_space_for(space) bands, plus a plane header
attribute mirror xattr_space_for(space) the subject's point, mirrored
Bands in the plane, for records whose address is synthetic:
y=0 volume metadata label + layout version
y=1 grants who may do what, where
y=2 xattr (reserved: attributes use the mirror space instead)
y=3 journal the decision trail, appended by `cube-os`
y=4 identity reserved for named ownership records
y=5 registry ordinal -> SpaceId, per domain
Mirroring in its own space, for records addressed by the subject they describe:
an attribute of the record at (x, y, z) is at (x, y, z). That needed a separate
space rather than a band, because a band consumes an axis and a subject's y is
data, not a category — a distinction that only showed up when a subject's
coordinates happened to look like a band's.
Each metadata space carries a plane header naming the domain it describes. That is not decoration: the derivation is a bit flip, so it is its own inverse, and a hiding rule based on presence alone cannot tell a plane from its domain — the first attempt hid the domain and emptied a listing. The header makes the direction a fact.
Still missing, in the order it should be done:
- POSIX views over grants — a mode bit is a grant with a one-point scope, and
chmod/chownbecome ways to write that grant. The OS layer already answers "may this identity do this" without them, which is why they are a view rather than a second authority model. - Journal ring semantics — the trail appends and reads back; wrap, retention and what must survive a crash are undecided.
- A general inode generation scheme, so a mount can reuse inodes rather than only ever allocating new ones.
5. How to see each package working
# Package 1+2: coordinates, records, headers, edges
cubecli --store /tmp/demo.store put root:1,2,3 hello
cubecli --store /tmp/demo.store hdr root:1,2,3
cubecli --store /tmp/demo.store link root:1,2,3 root:4,5,6
cubecli --store /tmp/demo.store follow root:1,2,3 0
# Package 4: code as data, runs, goldens, translation rules
cubecli --store /tmp/demo.store code root:10,0,0 const:3 const:4 mul halt
cubecli --store /tmp/demo.store run root:10,0,0
cubecli --store /tmp/demo.store capture root:10,0,0 root:20,0,0 root:21,0,0
cubecli --store /tmp/demo.store verify root:10,0,0 root:20,0,0 root:21,0,0
cubecli --store /tmp/demo.store lineage root:21,0,0 4
cubecli --store /tmp/demo.store rule code:1,2,0 mul shl
cubecli --store /tmp/demo.store mimic root:10,0,0
# Package 5: sealing by coordinate
cubecli --store /tmp/demo.store keys
cubecli --store /tmp/demo.store seal root:30,0,0 "a secret"
cubecli --store /tmp/demo.store open root:30,0,0
# Package 3: the namespace by path (C may be a space id, a name, or `c1`, `c2` …)
cubecli --store /tmp/demo.store ls /
cubecli --store /tmp/demo.store mkdir /c1/3
cubecli --store /tmp/demo.store write /c1/3/2/1 "hello namespace"
cubecli --store /tmp/demo.store stat /c1/3/2/1
cubecli --store /tmp/demo.store ls /c1/3/2
cubecli --store /tmp/demo.store alloc docs # label a space, then use /c2/...
cubecli --store /tmp/demo.store spaces
# Package 3 control plane: labels, authority, attributes
cubecli --store /tmp/demo.store label c1 "os volume"
cubecli --store /tmp/demo.store grant c1 root root o c1 # claim the domain
cubecli --store /tmp/demo.store grant c1 root alice rw /c1/3/2/1
cubecli --store /tmp/demo.store allows c1 alice /c1/3/2/1 r # allow
cubecli --store /tmp/demo.store allows c1 alice /c1/3/2/1 x # deny
cubecli --store /tmp/demo.store grants c1
cubecli --store /tmp/demo.store xattr /c1/3/2/1 user.note "kept"
hdr prints the flag word and the encrypted bit, which is how you can see the
metadata model doing its job rather than taking it on faith.
6. Where each decision is written down
| The name tier living at the edge, not in the store | CUTOVER-language-protocol.md |
| A-vs-B port ledger (per crate, with rationales) | this document + the commit messages on feat/kernelize-cube-rawblock |
|---|---|
| Coordinate width, curve choice, aggregation | DESIGN-coordinate-layer.md, REVIEW-cubelinux-pdf.md §2 |
| Entity/kernel model, edges, provenance | DESIGN-os-entities.md |
| Kernel direction | PLAN-kernelize-cube.md |
| Debugging/tracing plan | PLAN-debugging.md |
| Agent integration | INTEGRATION-cube-agent.md |
| A-vs-B port ledger (per crate, with rationales) | this document + the commit messages on feat/kernelize-cube-rawblock |