#![allow(dead_code)]
#[path = "../schema_support/mod.rs"]
pub mod support;
pub use support::{validate_schema, Env};
use std::collections::BTreeSet;
use std::path::PathBuf;
pub fn repo_root() -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR"))
}
pub fn schemas_dir() -> PathBuf {
repo_root().join("docs").join("schemas")
}
pub fn published_schema_text(id: &str) -> String {
let path = schemas_dir().join(format!("{id}.schema.json"));
std::fs::read_to_string(&path).unwrap_or_else(|e| panic!("cannot read {}: {e}", path.display()))
}
pub fn published_ids() -> BTreeSet<String> {
let mut ids = BTreeSet::new();
let entries = std::fs::read_dir(schemas_dir()).expect("docs/schemas must be readable");
for entry in entries.flatten() {
let name = entry.file_name().to_string_lossy().into_owned();
if let Some(stem) = name.strip_suffix(".schema.json") {
ids.insert(stem.to_string());
}
}
ids
}
pub struct LiveCase {
pub id: &'static str,
pub argv: &'static [&'static str],
}
pub const READ_ONLY_CASES: &[LiveCase] = &[
LiveCase {
id: "config-list",
argv: &["config", "list"],
},
LiveCase {
id: "embedding-status",
argv: &["embedding", "status"],
},
LiveCase {
id: "embedding-list",
argv: &["embedding", "list"],
},
LiveCase {
id: "slots-status",
argv: &["slots", "status"],
},
LiveCase {
id: "graph-stats",
argv: &["graph", "stats"],
},
LiveCase {
id: "graph-entities",
argv: &["graph", "entities"],
},
LiveCase {
id: "graph-entity-types",
argv: &["graph", "entity-types"],
},
LiveCase {
id: "graph-traverse",
argv: &["graph", "traverse", "--from", FIXTURE_ENTITY],
},
LiveCase {
id: "graph-recompute-degree",
argv: &["graph", "recompute-degree"],
},
LiveCase {
id: "vec-stats",
argv: &["vec", "stats"],
},
LiveCase {
id: "vec-orphan-list",
argv: &["vec", "orphan-list"],
},
LiveCase {
id: "prune-relations",
argv: &["prune-relations", "--relation", "depends-on", "--dry-run"],
},
LiveCase {
id: "split-body",
argv: &[
"split-body",
"--name",
FIXTURE_MEMORY,
"--threshold",
"1",
"--dry-run",
],
},
LiveCase {
id: "health",
argv: &["health"],
},
LiveCase {
id: "list",
argv: &["list"],
},
LiveCase {
id: "list",
argv: &["list", "--limit", "1"],
},
LiveCase {
id: "read",
argv: &["read", "--name", FIXTURE_MEMORY],
},
LiveCase {
id: "read",
argv: &["read", "--name", FIXTURE_MEMORY, "--with-graph"],
},
LiveCase {
id: "stats",
argv: &["stats"],
},
LiveCase {
id: "history",
argv: &["history", "--name", FIXTURE_MEMORY],
},
LiveCase {
id: "history",
argv: &["history", "--name", FIXTURE_MEMORY, "--diff"],
},
LiveCase {
id: "related",
argv: &["related", "--name", FIXTURE_MEMORY],
},
LiveCase {
id: "memory-entities",
argv: &["memory-entities", "--name", FIXTURE_MEMORY],
},
LiveCase {
id: "memory-entities-reverse",
argv: &["memory-entities", "--entity", FIXTURE_ENTITY],
},
LiveCase {
id: "namespace-detect",
argv: &["namespace-detect"],
},
LiveCase {
id: "debug-schema",
argv: &["debug-schema"],
},
LiveCase {
id: "fts-stats",
argv: &["fts", "stats"],
},
LiveCase {
id: "fts-check",
argv: &["fts", "check"],
},
LiveCase {
id: "graph",
argv: &["graph", "--format", "json"],
},
LiveCase {
id: "migrate",
argv: &["migrate"],
},
LiveCase {
id: "recall",
argv: &["recall", "corpo"],
},
LiveCase {
id: "hybrid-search",
argv: &["hybrid-search", "corpo"],
},
LiveCase {
id: "recall",
argv: &["recall", "corpo", "--fallback-fts-only"],
},
LiveCase {
id: "hybrid-search",
argv: &["hybrid-search", "corpo", "--fallback-fts-only"],
},
LiveCase {
id: "remember-dry-run",
argv: &[
"--llm-backend",
"none",
"remember",
"--name",
"mem-drift-dry-run",
"--type",
"project",
"--description",
"d",
"--body",
"corpo-que-nao-sera-gravado",
"--dry-run",
],
},
LiveCase {
id: "cleanup-orphans",
argv: &["cleanup-orphans", "--dry-run"],
},
LiveCase {
id: "enrich-status",
argv: &["enrich", "--status"],
},
LiveCase {
id: "normalize-entities",
argv: &["normalize-entities", "--dry-run"],
},
LiveCase {
id: "prune-ner",
argv: &["prune-ner", "--all", "--dry-run"],
},
LiveCase {
id: "reclassify-relation",
argv: &[
"reclassify-relation",
"--source",
FIXTURE_ENTITY,
"--target",
FIXTURE_ENTITY_B,
"--from-relation",
"depends-on",
"--to-relation",
"relates-to",
"--dry-run",
],
},
];
pub const FIXTURE_MEMORY: &str = "mem-type-drift-fixture";
pub const FIXTURE_MEMORY_SIBLING: &str = "mem-type-drift-fixture-sibling";
pub const FIXTURE_ENTITY_C: &str = "EntmemtypedriftfixtureGamma";
pub const FIXTURE_ENTITY: &str = "EntmemtypedriftfixtureAlpha";
pub const FIXTURE_ENTITY_B: &str = "EntmemtypedriftfixtureBeta";
pub fn fixture_env() -> Env {
let env = Env::new();
env.init();
let (from, to) = env.remember_with_entities(FIXTURE_MEMORY);
assert_eq!(
from, FIXTURE_ENTITY,
"the harness changed how it derives entity names, so `graph traverse` \
is now starting from an entity that does not exist and would validate \
an empty answer instead of a populated one"
);
assert_eq!(
to, FIXTURE_ENTITY_B,
"the harness changed how it derives entity names, so every case naming \
the second entity is now acting on something that does not exist"
);
env.cmd()
.args([
"link",
"--from",
&from,
"--to",
&to,
"--relation",
"depends-on",
"--namespace",
"global",
])
.assert()
.success();
let sibling_ents = env.tmp.path().join("sibling_entities.json");
std::fs::write(
&sibling_ents,
format!(r#"[{{"name":"{FIXTURE_ENTITY_C}","entity_type":"concept"}}]"#),
)
.expect("writing the sibling entities file failed");
env.cmd()
.args([
"--llm-backend",
"none",
"remember",
"--name",
FIXTURE_MEMORY_SIBLING,
"--type",
"project",
"--description",
"sibling of the fixture memory, one hop away through Gamma",
"--body",
"corpo-irmao-para-truncation-e-related",
"--entities-file",
sibling_ents.to_str().expect("path is not valid UTF-8"),
])
.assert()
.success();
env.cmd()
.args([
"link",
"--from",
FIXTURE_ENTITY_B,
"--to",
FIXTURE_ENTITY_C,
"--relation",
"relates-to",
"--namespace",
"global",
])
.assert()
.success();
env
}
pub fn check_argv(env: &Env, id: &str, argv: &[&str]) {
let output = env
.cmd()
.args(argv)
.output()
.unwrap_or_else(|e| panic!("[{id}] failed to spawn: {e}"));
assert!(
output.status.success(),
"[{id}] `{}` exited {:?}\nstdout: {}\nstderr: {}",
argv.join(" "),
output.status.code(),
String::from_utf8_lossy(&output.stdout),
String::from_utf8_lossy(&output.stderr),
);
let instance = Env::parse_stdout(&output, id);
validate_schema(id, &published_schema_text(id), &instance);
}
pub fn check_case(env: &Env, case: &LiveCase) {
check_argv(env, case.id, case.argv);
}