use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::Arc;
use std::time::{Duration, Instant};
use macrame::prelude::*;
const TS: &str = "2026-01-01T00:00:00.000000Z";
const OPEN: &str = "9999-12-31T23:59:59.999999Z";
const CONTROL_OPENS: usize = 48;
const READERS: usize = 16;
struct Args {
arm: String,
secs: u64,
runs: usize,
child: bool,
}
fn parse() -> Args {
let mut a = Args {
arm: "claim".into(),
secs: 20,
runs: 1,
child: false,
};
let argv: Vec<String> = std::env::args().skip(1).collect();
let mut i = 0;
while i < argv.len() {
match argv[i].as_str() {
"--arm" => {
a.arm = argv[i + 1].clone();
i += 2;
}
"--secs" => {
a.secs = argv[i + 1].parse().unwrap();
i += 2;
}
"--runs" => {
a.runs = argv[i + 1].parse().unwrap();
i += 2;
}
"--child" => {
a.child = true;
i += 1;
}
other => panic!("unknown argument {other}"),
}
}
a
}
fn main() {
let args = parse();
if args.child || args.runs <= 1 {
run_arm(&args.arm, args.secs);
} else {
supervise(&args);
}
}
fn supervise(args: &Args) {
let exe = std::env::current_exe().expect("current_exe");
println!(
"R15 soak: arm={} secs={} runs={}\n{}\n",
args.arm,
args.secs,
args.runs,
"-".repeat(60)
);
let mut faults = 0usize;
let mut other = 0usize;
for run in 1..=args.runs {
let t = Instant::now();
let status = std::process::Command::new(&exe)
.args([
"--child",
"--arm",
&args.arm,
"--secs",
&args.secs.to_string(),
])
.status()
.expect("spawn child");
let code = status.code();
let verdict = match code {
Some(0) => "clean",
Some(5) | Some(-1073741819) => {
faults += 1;
"R15 FAULT (access violation)"
}
_ => {
other += 1;
"other failure"
}
};
println!(
" run {run:>3}/{:<3} {:>6.1}s exit {:>12} {verdict}",
args.runs,
t.elapsed().as_secs_f64(),
code.map(|c| c.to_string())
.unwrap_or_else(|| "signal".into())
);
}
println!("\n{}", "-".repeat(60));
println!(
"arm={} faults {}/{} other failures {}",
args.arm, faults, args.runs, other
);
match (args.arm.as_str(), faults) {
("claim", 0) => println!(
"\nThe claim survives this load: one process, one file, a bounded set \n\
of connections opened once and never churned, {} readers and a \n\
saturated actor. Read it together with the control arm — a clean \n\
claim run means nothing on its own.",
READERS
),
("claim", n) => println!(
"\nR15 REACHES THE CLAIMED-SAFE SHAPE: {n} faults with no concurrent \n\
opens beyond `open()`. The mitigation's justification does not hold \n\
and the plan changes."
),
("control", 0) => println!(
"\nThe control did NOT fault, so this run provoked nothing and a clean \n\
claim arm is not evidence. Raise --runs or --secs before concluding \n\
anything from either arm."
),
("control", n) => println!(
"\nThe control faulted {n} times, so the harness does provoke R15 and \n\
a clean claim arm is a real negative."
),
_ => {}
}
std::process::exit(if other > 0 { 1 } else { 0 });
}
fn run_arm(arm: &str, secs: u64) {
let rt = tokio::runtime::Builder::new_multi_thread()
.enable_all()
.build()
.unwrap();
rt.block_on(async move {
match arm {
"claim" => soak(secs, false).await,
"control" => soak(secs, true).await,
other => panic!("unknown arm {other}"),
}
});
}
async fn soak(secs: u64, with_open_storm: bool) {
let dir = tempfile::TempDir::new().unwrap();
let db = Arc::new(Database::open(dir.path().join("soak.db")).await.unwrap());
db.write_concepts(
(0..500)
.map(|i| {
ConceptUpsert::new(format!("c{i:05}"), format!("C{i}"))
.content("body")
.valid_from(TS)
})
.collect(),
)
.await
.unwrap();
db.bulk_import(
(1..500)
.map(|i| {
EdgeAssertion::new("c00000", format!("c{i:05}"), "LINKS")
.valid_from(TS)
.valid_to(OPEN)
})
.collect(),
)
.await
.unwrap();
let deadline = Instant::now() + Duration::from_secs(secs);
let reads = Arc::new(AtomicU64::new(0));
let writes = Arc::new(AtomicU64::new(0));
let opens = Arc::new(AtomicU64::new(0));
let mut tasks = Vec::new();
for r in 0..READERS {
let db = Arc::clone(&db);
let reads = Arc::clone(&reads);
tasks.push(tokio::spawn(async move {
while Instant::now() < deadline {
let _ = db.load_subgraph("c00000", 2, TS, 64 << 20).await;
let _ = macrame::temporal::reconstruct(db.read_conn(), TS, None, None).await;
reads.fetch_add(2, Ordering::Relaxed);
if r == 0 {
tokio::task::yield_now().await;
}
}
}));
}
{
let db = Arc::clone(&db);
let writes = Arc::clone(&writes);
tasks.push(tokio::spawn(async move {
let mut i = 0u64;
while Instant::now() < deadline {
let _ = db
.write_concepts(vec![ConceptUpsert::new(
format!("w{i:09}"),
format!("W{i}"),
)
.content("body")
.valid_from(TS)])
.await;
writes.fetch_add(1, Ordering::Relaxed);
i += 1;
}
}));
}
if with_open_storm {
let storm_dir = dir.path().to_path_buf();
let opens = Arc::clone(&opens);
tasks.push(tokio::spawn(async move {
let mut round = 0u64;
while Instant::now() < deadline {
let mut batch = Vec::new();
for i in 0..CONTROL_OPENS {
let p = storm_dir.join(format!("storm-{round}-{i}.db"));
batch.push(tokio::spawn(async move {
let d = libsql::Builder::new_local(&p).build().await.unwrap();
let c = d.connect().unwrap();
let _ = c.query("SELECT 1", ()).await;
}));
}
for h in batch {
let _ = h.await;
}
opens.fetch_add(CONTROL_OPENS as u64, Ordering::Relaxed);
round += 1;
}
}));
}
for t in tasks {
let _ = t.await;
}
eprintln!(
" [child] reads={} writes={} concurrent_opens={}",
reads.load(Ordering::Relaxed),
writes.load(Ordering::Relaxed),
opens.load(Ordering::Relaxed)
);
Arc::into_inner(db).unwrap().close().await.unwrap();
}