#![forbid(unsafe_code)]
#![deny(rust_2018_idioms, unreachable_pub)]
use std::sync::Arc;
use std::time::Instant;
use lunaris::{CodingSessionMemory, Lunaris};
#[tokio::test]
#[ignore = "requires MOON_URL; un-ignored by integration.yml's lunaris-memory step"]
async fn helios_chat_10k_turns_dual_backend() -> anyhow::Result<()> {
for url_env in ["MOON_URL"] {
let Some(url) = probe_backend(url_env) else {
continue;
};
eprintln!("\n=== chat 10k turns: {url_env} ({url}) ===");
let lunaris = Arc::new(Lunaris::open(&url).await?);
let session_id = format!("smoke-chat-{}", ulid::Ulid::new());
let pad =
CodingSessionMemory::new(lunaris.clone(), lunaris_core::Scope::dev(), &session_id);
let turns: usize = std::env::var("LUNARIS_HELIOS_SMOKE_TURNS")
.ok()
.and_then(|v| v.parse().ok())
.unwrap_or(200);
let mut ingest_samples_ms: Vec<f64> = Vec::with_capacity(turns);
let mut recall_samples_ms: Vec<f64> = Vec::with_capacity(turns);
for i in 0..turns {
let path = format!("turn-{i:06}.md");
let content = format!(
"Turn {i}: hello from chat smoke. The quick brown fox jumps over the lazy dog."
);
let t0 = Instant::now();
pad.write(&path, content.clone()).await?;
ingest_samples_ms.push(t0.elapsed().as_secs_f64() * 1000.0);
let t1 = Instant::now();
let _read = pad.read(&path).await?;
recall_samples_ms.push(t1.elapsed().as_secs_f64() * 1000.0);
if i % 10 == 0 && i > 0 {
let prior = format!("turn-{:06}.md", i - 1);
pad.edit(&prior, "hello", "HELLO").await?;
let _ = pad.grep("brown fox", 5).await?;
}
}
let ingest_p50 = percentile(&mut ingest_samples_ms, 50.0);
let ingest_p99 = percentile(&mut ingest_samples_ms, 99.0);
let recall_p50 = percentile(&mut recall_samples_ms, 50.0);
let recall_p99 = percentile(&mut recall_samples_ms, 99.0);
let (ingest_budget, recall_budget) = budgets(url_env);
eprintln!(
"{url_env} chat: turns={turns} ingest_p50={ingest_p50:.2}ms ingest_p99={ingest_p99:.2}ms (budget {ingest_budget}ms) recall_p50={recall_p50:.2}ms recall_p99={recall_p99:.2}ms (budget {recall_budget}ms)"
);
check_budget(url_env, "ingest_p50", ingest_p50, ingest_budget);
check_budget(url_env, "recall_p50", recall_p50, recall_budget);
let _ = pad.forget().await?;
}
Ok(())
}
#[tokio::test]
#[ignore = "requires MOON_URL; un-ignored by integration.yml's lunaris-memory step (~5min only when DOCS=50000; the default is small)"]
async fn helios_doc_rag_50k_md_dual_backend() -> anyhow::Result<()> {
for url_env in ["MOON_URL"] {
let Some(url) = probe_backend(url_env) else {
continue;
};
eprintln!("\n=== doc rag md: {url_env} ({url}) ===");
let lunaris = Arc::new(Lunaris::open(&url).await?);
let session_id = format!("smoke-rag-{}", ulid::Ulid::new());
let pad =
CodingSessionMemory::new(lunaris.clone(), lunaris_core::Scope::dev(), &session_id);
let docs: u64 = std::env::var("LUNARIS_HELIOS_SMOKE_DOCS")
.ok()
.and_then(|v| v.parse().ok())
.unwrap_or(1_000);
let bulk_started = Instant::now();
let written =
lunaris_bench::build_md_doc_corpus(lunaris.storage().as_ref(), docs, 0xDEAD_BEEF)
.await?;
eprintln!(
"{url_env} bulk-ingested {written} docs in {:.2}s",
bulk_started.elapsed().as_secs_f64()
);
let mut grep_samples_ms: Vec<f64> = Vec::with_capacity(100);
for q in 0..100u32 {
let t = Instant::now();
let _ = pad.grep(&format!("Section {} Lorem", q % 8), 5).await?;
grep_samples_ms.push(t.elapsed().as_secs_f64() * 1000.0);
}
let grep_p50 = percentile(&mut grep_samples_ms, 50.0);
let grep_p99 = percentile(&mut grep_samples_ms, 99.0);
let (_, recall_budget) = budgets(url_env);
eprintln!(
"{url_env} rag: docs={docs} grep_p50={grep_p50:.2}ms grep_p99={grep_p99:.2}ms (budget {recall_budget}ms)"
);
check_budget(url_env, "grep_p50", grep_p50, recall_budget);
}
Ok(())
}
fn probe_backend(env_name: &str) -> Option<String> {
lunaris_test_harness::live_probe::probe_url_env(env_name)
}
fn budgets(env_name: &str) -> (f64, f64) {
match env_name {
"MOON_URL" => (50.0, 25.0), _ => (f64::INFINITY, f64::INFINITY),
}
}
fn check_budget(env_name: &str, metric: &str, value: f64, budget: f64) {
if value <= budget {
return;
}
let ratio = value / budget;
panic!(
"{env_name} {metric}={value:.2}ms exceeds budget {budget}ms ({ratio:.2}x) — Moon hard-fail"
);
}
fn percentile(samples: &mut [f64], pct: f64) -> f64 {
if samples.is_empty() {
return 0.0;
}
samples.sort_by(|a, b| a.partial_cmp(b).unwrap_or(std::cmp::Ordering::Equal));
let idx = ((samples.len() as f64) * (pct / 100.0)) as usize;
let idx = idx.min(samples.len() - 1);
samples[idx]
}
#[test]
fn percentile_empty_returns_zero() {
let mut v: Vec<f64> = Vec::new();
assert_eq!(percentile(&mut v, 50.0), 0.0);
}
#[test]
fn percentile_p50_picks_middle() {
let mut v = vec![10.0, 20.0, 30.0, 40.0, 50.0];
assert_eq!(percentile(&mut v, 50.0), 30.0);
}
#[test]
fn budgets_table_matches_requirements() {
assert_eq!(budgets("MOON_URL"), (50.0, 25.0));
assert_eq!(budgets("PG_URL"), (f64::INFINITY, f64::INFINITY));
assert_eq!(budgets("UNKNOWN"), (f64::INFINITY, f64::INFINITY));
}
#[test]
fn check_budget_within_budget_does_not_panic() {
check_budget("MOON_URL", "ingest_p50", 10.0, 50.0);
check_budget("MOON_URL", "recall_p50", 24.0, 25.0);
}
#[test]
#[should_panic(expected = "Moon hard-fail")]
fn check_budget_moon_over_budget_hard_fails() {
check_budget("MOON_URL", "ingest_p50", 100.0, 50.0);
}
#[test]
#[should_panic(expected = "Moon hard-fail")]
fn check_budget_far_over_budget_still_hard_fails() {
check_budget("MOON_URL", "ingest_p50", 250.0, 100.0);
}
#[test]
fn coding_session_memory_v2_surface_matches_v1_exactly() {
let src = include_str!("../src/recipes/coding_session_memory.rs");
let production = src.split("#[cfg(test)]").next().unwrap_or(src);
let pub_fns =
production.matches(" pub fn ").count() + production.matches(" pub async fn ").count();
assert_eq!(
pub_fns, 10,
"HELIOS-01 cross-crate sentinel: expected exactly 10 public methods \
(9 on CodingSessionMemory + AsOfScratchpad::read); got {pub_fns}. \
Any drift here vs the in-lib sentinel is a contract violation. \
Re-baselined 9→10 alongside the in-lib sentinel when `write_dated` \
landed (session-date grounding — the recipe needs a write that \
stamps the observation's own t_ref instead of ingest wall-clock)."
);
}
#[tokio::test]
#[ignore = "requires MOON_URL; un-ignored by integration.yml's lunaris-memory step"]
async fn coding_session_memory_v2_delegation_round_trip() -> anyhow::Result<()> {
for url_env in ["MOON_URL"] {
let Some(url) = probe_backend(url_env) else {
continue;
};
eprintln!("\n=== v2 delegation round-trip: {url_env} ({url}) ===");
let lunaris = Arc::new(Lunaris::open(&url).await?);
let session_id = format!("smoke-v2-rt-{}", ulid::Ulid::new());
let pad =
CodingSessionMemory::new(lunaris.clone(), lunaris_core::Scope::dev(), &session_id);
pad.write("note.md", "hello v2").await?;
let round_trip = pad.read("note.md").await?;
assert_eq!(
round_trip.as_deref(),
Some("hello v2"),
"{url_env}: v2 write→read round-trip lost or reshaped the payload"
);
let _ = pad.forget().await?;
}
Ok(())
}