Plan M5a: local memory in 15 tasks

memoryd (files, the check, edits, journal, index, recall, serving),
the memory tools and built-in grants in brokerd, the memory block in
loopd, bxctl reindex and memory, and the device checks with memoryd.

Each task was built as a reference and gated. Each was replayed on its
own at its end state (854 to 936 tests) and mutation-checked. Each
skeleton compiles and fails its tests. Every todo comment was read
beside its signature.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-24 15:32:54 -07:00
co-authored by Claude Opus 5.5
parent 19fd74db6e
commit de1032157b
76 changed files with 8382 additions and 0 deletions
@@ -0,0 +1,40 @@
//! Starting `memoryd` for the device tests, with the repository's starter `soul.md`: `loopd`
//! starts no session without the memory block. Do not edit.
use std::path::Path;
use std::process::{Child, Command};
use std::thread;
use std::time::Duration;
/// Write `memoryd.toml` into `home`, start `memoryd serve`, and wait for its `loopd` socket.
pub fn start(home: &Path) -> Child {
let root = Path::new(env!("CARGO_MANIFEST_DIR")).join("../..");
let config = home.join("memoryd.toml");
std::fs::write(
&config,
format!(
"[paths]\nhome = \"{}\"\n[memory]\nsoul_starter = \"{}\"\n",
home.display(),
root.join("config/soul.md").display()
),
)
.unwrap();
let socket = home.join("run").join("loop-memory").join("memory.sock");
let _ = std::fs::remove_file(&socket);
let bin = std::env::var("BOXMAKER_MEMORYD").expect("BOXMAKER_MEMORYD is not set");
let mut child = Command::new(bin)
.arg("serve")
.arg("--config")
.arg(&config)
.spawn()
.expect("cannot start memoryd");
for _ in 0..600 {
if socket.exists() {
return child;
}
thread::sleep(Duration::from_millis(100));
}
let _ = child.kill();
let _ = child.wait();
panic!("memoryd did not come up within 60 s");
}