cubesys/cubecli: session note/message-save-path (notes) — WordFlags-tagged CZYX note log (doc_type=note, per-session owner + created_at day), store_note/list/search/show + note_command dispatcher, durable CubeStore+WAL+checkpoint; cube note add|list|search|show. New cubesys::notes module w/ 3 tests; workspace check green.

This commit is contained in:
2026-09-08 04:01:06 -04:00
parent cc896fc336
commit a601710d50
4 changed files with 445 additions and 7 deletions
+53 -7
View File
@@ -62,9 +62,33 @@ fn is_command_word(w: &str) -> bool {
| "rollback"
| "stats"
| "audit"
| "note"
| "notes"
)
}
/// Open (or create) the durable session-note store. Notes persist across CLI
/// invocations and sessions — the CUBE "message save path" — via the WAL +
/// checkpoint store. The directory is `$CUBE_NOTES_DIR` (`~/.cubelinux-notes`).
fn open_notes_store() -> cubesys::store::ConcurrentStore {
let dir = std::env::var("CUBE_NOTES_DIR").unwrap_or_else(|_| {
format!(
"{}/.cubelinux-notes",
std::env::var("HOME").unwrap_or_else(|_| "/tmp".to_string())
)
});
cubesys::store::ConcurrentStore::open(
&format!("{dir}/notes.store"),
&format!("{dir}/notes.wal"),
&format!("{dir}/recovery.log"),
cubesys::store::DurabilityConfig::default(),
)
.unwrap_or_else(|e| {
eprintln!("error: cannot open notes store {dir}: {e}");
std::process::exit(1);
})
}
fn main() {
let args: Vec<String> = std::env::args().collect();
match args.get(1).map(|s| s.as_str()) {
@@ -75,12 +99,29 @@ fn main() {
// the coordinate-addressed API a real CLI surface the OS can call.
Some(word) if is_command_word(word) => {
let line = args[1..].join(" ");
let mut session = Session::new();
match session.exec(&line) {
Ok(out) => println!("{out}"),
Err(e) => {
eprintln!("error: {e}");
std::process::exit(1);
// Session notes live in their own DURABLE store so a note written
// in one session is reviewable in the next (the message save path).
if word == "note" || word == "notes" {
let store = open_notes_store();
let res = cubesys::notes::note_command(&store, &line);
// Force a durable flush/checkpoint before exiting so the note is
// persisted even though this process (the CLI) is short-lived.
store.checkpoint();
match res {
Ok(out) => println!("{out}"),
Err(e) => {
eprintln!("error: {e}");
std::process::exit(1);
}
}
} else {
let mut session = Session::new();
match session.exec(&line) {
Ok(out) => println!("{out}"),
Err(e) => {
eprintln!("error: {e}");
std::process::exit(1);
}
}
}
}
@@ -144,6 +185,11 @@ fn print_help() {
stat <path> getattr via cubefs\n \
seal <path> <K.Z.Y.X|auto> <tf> encrypt a record (tf: none|gcm|chacha|xts)\n \
open <path> <K.Z.Y.X|auto> <tf> decrypt + decode + run a sealed record\n \
keyinit ensure the OS Null-space keystore exists\n"
keyinit ensure the OS Null-space keystore exists\n \
note <text> add a session note (durable, WordFlags-tagged)\n \
note list [session] list notes (default: today's session)\n \
note search <text> search notes across sessions\n \
note show <C.Z.Y.X> show one note\n \
notes alias for `note list`\n"
);
}