Files
sausage/host/src/world.rs
T
surma 57a47b069e host: process table, shell, coreutils and harness (T8, T9)
T8: sausage:process WIT (spawn, wait, kill), one store per process over the
shared root, /proc/processes, /run, pipeline and cancellation groups, Exec.
brush and 78 uutils commands; the shared cwd-init object sets the cwd from PWD
and keeps numeric exit codes. The corpus matches native bash.

T9: V8 (deno_core) runs pi-durable, pi-ai and chord; SQLite storage in
<dir>/host/harness.sqlite (WAL, synchronous=FULL); file tools on the VFS, bash
through Exec; resumes after SIGKILL.
2026-11-06 16:34:34 +00:00

61 lines
2.2 KiB
Rust

//! A world directory and the one virtual root that host code and guests share.
//!
//! Layout of a world directory:
//! - `world/`: the virtual root `/` that every guest sees. Agents change everything in it.
//! - `host/`: host state outside the sandbox (harness storage, later the vault). No guest sees it.
use sausage_vfs::{Generated, Host, Layer, Memory, Mounts, Process};
use std::{
path::{Path, PathBuf},
sync::Arc,
};
/// An open world. `root` is the filesystem every guest sees as `/`; host code (the harness's file
/// tools) reads and writes through the same layer, so both always see the same files.
pub struct World {
pub root: Arc<dyn Layer>,
/// The host state folder, `<dir>/host`.
pub host_dir: PathBuf,
/// Live process metadata shared with the process table.
pub processes: crate::process::Processes,
}
impl World {
/// Open (and create if missing) the world directory `dir`, including `/proc` and `/run` mounts.
pub fn open(dir: &Path) -> anyhow::Result<Self> {
let root_dir = dir.join("world");
let host_dir = dir.join("host");
std::fs::create_dir_all(&root_dir)?;
std::fs::create_dir_all(&host_dir)?;
let mut mounts = Mounts::default();
mounts.mount(
"/",
Arc::new(Host::new(&root_dir, Process::default())?),
false,
);
let processes: crate::process::Processes =
Arc::new(std::sync::Mutex::new(Default::default()));
let snapshot = processes.clone();
let mut proc = Generated::default();
proc.insert("/processes", move || {
let mut text = String::from("PID\tPPID\tSTATE\tCWD\tARGV\n");
for (pid, info) in snapshot.lock().unwrap().iter() {
text.push_str(&format!(
"{pid}\t{}\t{}\t{}\t{}\n",
info.parent,
info.state,
info.cwd,
info.argv.join(" ")
));
}
Ok(text.into_bytes())
});
mounts.mount("/proc", Arc::new(proc), true);
mounts.mount("/run", Arc::new(Memory::default()), false);
Ok(World {
root: Arc::new(mounts),
host_dir,
processes,
})
}
}