Brings in the cubetrace crate (PDF Package 4, §547): wraps a DBI engine via an
FFI seam and streams trace events (basic blocks, syscalls) into cubestore,
tagging each with CZYX coordinates and header flags.
- Cargo.toml: register cubetrace workspace member
- cubeai/src/lib.rs, cubedbt/src/lib.rs: DBT/AI rule + trace integration edits
- cubecode/src/{cb,cell}.rs: code-cell bytecode/module plumbing for traces
- cubesys/src/commands.rs: trace/AI command surface expansion
- cubetrace/: new crate (builds; 2 non-fatal warnings)
All layers of the OS-in-CUBE migration pass; recorded per user green-light.
170 lines
6.9 KiB
Rust
170 lines
6.9 KiB
Rust
//! CUBELinux-2 cubebook / kernel-convention constants.
|
||
//!
|
||
//! These are the conventions the *OS* layer uses to store its computational
|
||
//! behavior in CUBE. Per the PDF (Package 4, and the "behavior descriptors"
|
||
//! discussion at PDF §524–525), functions/operators that live in CUBE are:
|
||
//! * addressed in a reserved `C` axis band (here `c210..=c219`),
|
||
//! * tagged with a `kind` (`fn`/`kernel`/`layer`/`checkpoint`/`variant`), and
|
||
//! * annotated with *behavior descriptor* flags carried in the record
|
||
//! header's out-of-band flag bits (tag 12, see cubestore encode/decode).
|
||
//!
|
||
//! The full spec-derived descriptor set (PDF §524–525) is: "pure function,"
|
||
//! "I/O heavy," "allocates memory," "touches network," "hot path," and
|
||
//! "security sensitive." We store each directly as a dedicated header-flag bit
|
||
//! inside the spare 8..=15 range, deliberately leaving bit 12
|
||
//! (`cubecrypt::HEADER_FLAG_ENCRYPTED`) clear. `CubeHeader::refresh_flags()`
|
||
//! preserves spare bits 8..=15, so a header carrying descriptors survives an
|
||
//! encode→decode→refresh round-trip.
|
||
//!
|
||
//! This is deliberately NOT a store-IO model: the cubevm never reads or writes
|
||
//! OS state records directly. The OS's *decisions/computation* live as CUBE
|
||
//! kernels; the native OS layer is a thin effector that reads a kernel's
|
||
//! computed result and applies the effect (writes the record, runs the
|
||
//! command). See `cubesys/src/commands.rs` `tick` + `native-apply`.
|
||
|
||
/// First `C` axis value reserved for OS operator kernels (call-graph roots and
|
||
/// leaves). The OS keeps its behavioral substrate here, separate from the
|
||
/// `c200` operational-snapshot data band and the `c001/c002` doc examples.
|
||
pub const C_OS_KERNEL: u8 = 210;
|
||
|
||
/// `C` axis band for OS *data* records the native layer writes after a kernel
|
||
/// decides an effect (kept distinct from the compute-kernel band above).
|
||
pub const C_OS_EFFECT: u8 = 211;
|
||
|
||
/// Header-flag bits reserved for the behavior-descriptor field. Six spec
|
||
/// descriptors, each a dedicated bit in the spare 8..=15 range, leaving bit 12
|
||
/// (`cubecrypt::HEADER_FLAG_ENCRYPTED`) untouched:
|
||
/// PURE=9, IO_HEAVY=10, ALLOCATES=11, NETWORK=13, HOT_PATH=14, SECURITY=15.
|
||
pub const HEADER_FLAG_BEHAVIOR: u16 = 0b1110_1110_0000_0000; // bits 9,10,11,13,14,15 (bit12 reserved)
|
||
|
||
/// Behavior descriptors for an OS operator kernel (PDF §524–525, full set).
|
||
///
|
||
/// Each variant is stored directly as its dedicated header-flag bit (subset of
|
||
/// `HEADER_FLAG_BEHAVIOR`), so `Behavior` carries the raw descriptor bits and
|
||
/// round-trips through the header codec without bit-shift collisions.
|
||
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
|
||
pub struct Behavior(pub u16);
|
||
|
||
impl Behavior {
|
||
/// Pure function: no side effects, deterministic on inputs.
|
||
pub const PURE: u16 = 1 << 9; // 0x0200
|
||
/// I/O heavy: performs significant store/device I/O.
|
||
pub const IO_HEAVY: u16 = 1 << 10; // 0x0400
|
||
/// Allocates memory: grows the heap / maps pages.
|
||
pub const ALLOCATES: u16 = 1 << 11; // 0x0800
|
||
/// Touches network: performs socket/link I/O (security-relevant surface).
|
||
pub const NETWORK: u16 = 1 << 13; // 0x2000
|
||
/// Hot path: executed frequently; a candidate for optimization/variant swap.
|
||
pub const HOT_PATH: u16 = 1 << 14; // 0x4000
|
||
/// Security sensitive: elevated privilege / trust boundary crossing.
|
||
pub const SECURITY_SENSITIVE: u16 = 1 << 15; // 0x8000
|
||
|
||
/// Combine descriptor bits (e.g. `Behavior::PURE | Behavior::HOT_PATH`).
|
||
pub fn new(bits: u16) -> Self {
|
||
Behavior(bits & HEADER_FLAG_BEHAVIOR)
|
||
}
|
||
|
||
/// Encode into the out-of-band header flag bits.
|
||
pub fn to_flags(self) -> u16 {
|
||
self.0 & HEADER_FLAG_BEHAVIOR
|
||
}
|
||
|
||
/// Decode from a raw 16-bit flag word (keeps only the behavior bits).
|
||
pub fn from_flags(flags: u16) -> Self {
|
||
Behavior(flags & HEADER_FLAG_BEHAVIOR)
|
||
}
|
||
|
||
/// True if any descriptor bit is set.
|
||
pub fn is_any(self) -> bool {
|
||
self.0 != 0
|
||
}
|
||
|
||
/// Human-readable descriptor tags (used by `ls`/`stat` and the effector).
|
||
pub fn tags(self) -> Vec<&'static str> {
|
||
let mut out = Vec::new();
|
||
if self.0 & Self::PURE != 0 {
|
||
out.push("pure");
|
||
}
|
||
if self.0 & Self::IO_HEAVY != 0 {
|
||
out.push("io");
|
||
}
|
||
if self.0 & Self::ALLOCATES != 0 {
|
||
out.push("alloc");
|
||
}
|
||
if self.0 & Self::NETWORK != 0 {
|
||
out.push("net");
|
||
}
|
||
if self.0 & Self::HOT_PATH != 0 {
|
||
out.push("hot");
|
||
}
|
||
if self.0 & Self::SECURITY_SENSITIVE != 0 {
|
||
out.push("sec");
|
||
}
|
||
out
|
||
}
|
||
}
|
||
|
||
#[cfg(test)]
|
||
mod tests {
|
||
use super::*;
|
||
use cubecoords::{CubeHeader, Czyx};
|
||
use cubestore::{CubeStore, HashBackend};
|
||
|
||
#[test]
|
||
fn behavior_round_trips_through_store() {
|
||
// All six spec descriptors must survive the real store round-trip
|
||
// (what native-apply reads back). This is the exact field the
|
||
// effector inspects; an earlier 3-bit mask (0x7000) silently dropped
|
||
// HOT_PATH (bit 15) and collided with ENCRYPTED (bit 12).
|
||
let b = Behavior::new(
|
||
Behavior::PURE | Behavior::IO_HEAVY | Behavior::ALLOCATES | Behavior::NETWORK,
|
||
);
|
||
let raw = b.to_flags();
|
||
assert_eq!(
|
||
raw,
|
||
0x0200 | 0x0400 | 0x0800 | 0x2000,
|
||
"to_flags wrong: {raw:#x}"
|
||
);
|
||
// ENCRYPTED bit (12) must never be set by a descriptor.
|
||
assert_eq!(raw & (1 << 12), 0, "descriptor must not set ENCRYPTED bit");
|
||
|
||
let mut store = CubeStore::new(HashBackend::new());
|
||
let coord = Czyx::new(210, 1, 1, 3);
|
||
let mut h = CubeHeader::new();
|
||
h.doc_type = Some("kernel".into());
|
||
h.title = Some("summarize-procs".into());
|
||
h.flags.0 |= raw;
|
||
h.refresh_flags();
|
||
store.put_record(coord, &h, &[1, 2, 3]);
|
||
|
||
let (read_h, _) = store.get_record(&coord).expect("record present");
|
||
let back = Behavior::from_flags(read_h.flags.bits());
|
||
assert_eq!(
|
||
back,
|
||
b,
|
||
"behavior dropped on store round-trip: stored {raw:#x}, got {:#x}",
|
||
read_h.flags.bits()
|
||
);
|
||
}
|
||
|
||
#[test]
|
||
fn security_sensitive_bit_used_and_round_trips() {
|
||
// Explicitly cover the 6th spec descriptor (security sensitive, bit15).
|
||
let b = Behavior::new(Behavior::SECURITY_SENSITIVE | Behavior::HOT_PATH);
|
||
let mut store = CubeStore::new(HashBackend::new());
|
||
let coord = Czyx::new(210, 1, 1, 5);
|
||
let mut h = CubeHeader::new();
|
||
h.doc_type = Some("kernel".into());
|
||
h.title = Some("privileged-op".into());
|
||
h.flags.0 |= b.to_flags();
|
||
h.refresh_flags();
|
||
store.put_record(coord, &h, &[]);
|
||
let (read_h, _) = store.get_record(&coord).expect("record present");
|
||
assert_eq!(
|
||
Behavior::from_flags(read_h.flags.bits()),
|
||
b,
|
||
"security-sensitive descriptor lost on round-trip"
|
||
);
|
||
}
|
||
}
|