use std::fs;
use std::path::Path;
const TEMPLATE_DIR: &str = "src/docs/reference/templates";
const OWNED_TEMPLATES: &[&str] = &[
"SOUL.md",
"USER.md",
"AGENTS.md",
"CODE.md",
"TOOLS.md",
"SECURITY.md",
"MEMORY.md",
"BOOT.md",
];
fn read_template(name: &str) -> String {
let path = Path::new(TEMPLATE_DIR).join(name);
fs::read_to_string(&path).unwrap_or_else(|_| panic!("template {name} must exist at {path:?}"))
}
#[test]
fn every_rule_template_has_ownership_header() {
for name in OWNED_TEMPLATES {
let content = read_template(name);
assert!(
content.contains("> **Owns:**"),
"{name} must open with a `> **Owns:** …` ownership-map header so RSI \
and future edits know what this file is the single source of truth for"
);
}
}
#[test]
fn enforced_gates_live_in_agents_not_soul() {
let soul = read_template("SOUL.md");
let agents = read_template("AGENTS.md");
assert!(
agents.contains("create PRs only") && agents.contains("NEVER DO WITHOUT EXPLICIT APPROVAL"),
"AGENTS.md must own the enforced hard rules / permission gates"
);
assert!(
!soul.contains("create PRs only"),
"SOUL.md must NOT duplicate the commit/push gate — it lives in AGENTS.md"
);
assert!(
soul.contains("AGENTS.md"),
"SOUL.md must point to AGENTS.md for the hard rules"
);
}
#[test]
fn preamble_and_rsi_route_hard_rules_to_agents() {
use crate::brain::prompt_builder::BRAIN_PREAMBLE;
assert!(
BRAIN_PREAMBLE.contains("AGENTS.md")
&& BRAIN_PREAMBLE.contains("hard rules")
&& BRAIN_PREAMBLE.contains("Always-loaded"),
"preamble must route hard rules to the always-loaded AGENTS.md"
);
const RSI_SRC: &str = include_str!("../brain/rsi.rs");
assert!(
RSI_SRC.contains("ALWAYS-LOADED") && RSI_SRC.contains("hard rules"),
"RSI taxonomy must route learned hard rules to the always-loaded AGENTS.md"
);
}
#[test]
fn agents_documents_command_and_skill_discovery() {
let agents = read_template("AGENTS.md");
assert!(
agents.contains("Commands & Skills") && agents.contains("slash_command"),
"AGENTS.md must document how to discover/run user commands & skills"
);
assert!(
agents.contains("Available Commands & Skills"),
"AGENTS.md must reference the always-injected live commands/skills index"
);
}
#[test]
fn rsi_notes_new_commands_skills_are_auto_discoverable() {
const RSI_SRC: &str = include_str!("../brain/rsi.rs");
assert!(
RSI_SRC.contains("Available Commands & Skills")
|| RSI_SRC.contains("discoverable automatically"),
"RSI must note that a newly-applied command/skill is auto-discoverable via \
the injected index, so it isn't re-documented in a brain file"
);
}
#[test]
fn rust_first_policy_lives_only_in_code_md() {
const FULL_TEXT: &str = "always prioritize Rust-based crates";
assert!(
read_template("CODE.md").contains(FULL_TEXT),
"CODE.md must own the full Rust-First Policy"
);
for other in ["AGENTS.md", "BOOT.md"] {
let c = read_template(other);
assert!(
!c.contains(FULL_TEXT),
"{other} must NOT duplicate the Rust-First Policy text — point to CODE.md"
);
assert!(
c.contains("Rust-First") && c.contains("CODE.md"),
"{other} must keep a pointer to CODE.md for the Rust-First Policy"
);
}
}
#[test]
fn upgrade_procedure_lives_in_boot_md() {
assert!(
read_template("BOOT.md").contains("cargo build --release"),
"BOOT.md must own the upgrade procedure"
);
let agents = read_template("AGENTS.md");
assert!(
agents.contains("Upgrading") && agents.contains("BOOT.md"),
"AGENTS.md must point to BOOT.md for upgrading, not duplicate the steps"
);
}
#[test]
fn memory_save_triggers_live_in_the_always_loaded_file() {
let agents = read_template("AGENTS.md");
let boot = read_template("BOOT.md");
assert!(
agents.contains("What triggers a save to"),
"AGENTS.md must own the memory-save triggers: it is the always-loaded \
file, and a trigger that fires mid-session has to be in context then"
);
assert!(
boot.contains("AGENTS.md") && boot.contains("Auto-Save Important Memories"),
"BOOT.md must point at AGENTS.md for the triggers rather than restate them"
);
assert!(
!boot.contains("What triggers a save to"),
"BOOT.md must not keep a second copy of the trigger list"
);
assert!(
!boot.contains("The single home for \"when to save memory\""),
"BOOT.md's ownership header must stop claiming the memory triggers"
);
}
#[test]
fn templates_reference_no_personal_user_files() {
for name in OWNED_TEMPLATES.iter().chain(["HEARTBEAT.md"].iter()) {
let content = read_template(name);
for banned in ["VOICE.md", "AGENTVERSE.md"] {
assert!(
!content.contains(banned),
"{name} must not reference the user file {banned} — those are \
arbitrary user-created files, not canonical brain files"
);
}
}
}
#[test]
fn boot_md_documents_service_and_daemon_setup() {
let boot = read_template("BOOT.md");
assert!(
boot.contains("opencrabs service install"),
"BOOT.md must document `opencrabs service install` (systemd/launchd)"
);
assert!(
boot.contains("opencrabs daemon"),
"BOOT.md must mention the `opencrabs daemon` process the unit runs"
);
}
#[test]
fn deleted_templates_do_not_exist() {
for gone in ["VOICE.md", "BOOTSTRAP.md"] {
assert!(
!Path::new(TEMPLATE_DIR).join(gone).exists(),
"{gone} was removed as redundant — it must not come back"
);
}
}
#[test]
fn boot_md_is_seeded_and_dead_files_are_not() {
use crate::tui::onboarding::TEMPLATE_FILES;
assert!(
TEMPLATE_FILES.iter().any(|(n, _)| *n == "BOOT.md"),
"BOOT.md must be seeded so its on-demand load (and AGENTS.md's pointers \
to it) resolve for fresh users"
);
for gone in ["BOOTSTRAP.md", "VOICE.md"] {
assert!(
!TEMPLATE_FILES.iter().any(|(n, _)| *n == gone),
"{gone} must not be seeded"
);
}
}
#[test]
fn preamble_carries_brain_file_ownership_map() {
use crate::brain::prompt_builder::BRAIN_PREAMBLE;
assert!(
BRAIN_PREAMBLE.contains("BRAIN FILE OWNERSHIP"),
"the system preamble must teach the agent the brain-file ownership map"
);
for f in [
"SOUL.md",
"MEMORY.md",
"CODE.md",
"TOOLS.md",
"SECURITY.md",
"BOOT.md",
] {
assert!(
BRAIN_PREAMBLE.contains(f),
"preamble ownership map must name {f}"
);
}
assert!(
BRAIN_PREAMBLE.contains("never") && BRAIN_PREAMBLE.contains("duplicat"),
"preamble must state that a rule is never duplicated across files"
);
}
#[test]
fn rsi_taxonomy_routes_to_all_core_brain_files() {
const RSI_SRC: &str = include_str!("../brain/rsi.rs");
for f in [
"SOUL.md",
"USER.md",
"MEMORY.md",
"AGENTS.md",
"CODE.md",
"TOOLS.md",
"SECURITY.md",
"BOOT.md",
] {
assert!(
RSI_SRC.contains(f),
"RSI Target File Taxonomy must route improvements to {f}"
);
}
assert!(
RSI_SRC.contains("One kind of content per file"),
"RSI must state the one-kind-per-file ownership principle"
);
}
#[test]
fn memory_index_excludes_dead_files() {
use crate::memory::BRAIN_FILES;
for gone in ["BOOTSTRAP.md", "VOICE.md"] {
assert!(
!BRAIN_FILES.contains(&gone),
"memory index must not list the removed {gone}"
);
}
}
const DEAD_BRAIN_FILES: &[&str] = &["IDENTITY.md", "VOICE.md", "BOOTSTRAP.md"];
#[test]
fn user_facing_docs_do_not_reference_dead_brain_files() {
let mut checked = 0;
for path in ["README.md", "src/docs/start", TEMPLATE_DIR] {
for file in markdown_files(Path::new(path)) {
if file.ends_with("BRAIN_CONSTITUTION.md") {
continue;
}
let content = fs::read_to_string(&file).expect("doc reads");
for dead in DEAD_BRAIN_FILES {
assert!(
!content.contains(dead),
"{} references {dead}, which was removed from the brain-file set. \
Docs that promise a dead brain file produce workspaces carrying a \
file nothing reads.",
file.display()
);
}
checked += 1;
}
}
assert!(checked > 0, "scanned no docs, the paths must be wrong");
}
fn markdown_files(path: &Path) -> Vec<std::path::PathBuf> {
if path.is_file() {
return vec![path.to_path_buf()];
}
let mut out = Vec::new();
let Ok(entries) = fs::read_dir(path) else {
return out;
};
for entry in entries.flatten() {
let p = entry.path();
if p.is_dir() {
out.extend(markdown_files(&p));
} else if p.extension().is_some_and(|e| e == "md") {
out.push(p);
}
}
out
}
const SOUL_RULE_SECTIONS: &[&str] = &[
"## Your Role",
"## Operating Rules",
"## Epistemic Honesty",
"## Never Assume, Verify",
"## Fix, Don't Narrate",
];
#[test]
fn soul_operating_rules_are_their_own_sections() {
let soul = read_template("SOUL.md");
for heading in SOUL_RULE_SECTIONS {
assert!(
soul.lines().any(|l| l.trim_end() == *heading),
"SOUL.md must carry `{heading}` as a top-level section on its own line. \
Folded into another section, rsi_sync will never deliver it to an \
existing install."
);
}
}
#[test]
fn epistemic_posture_and_protocol_do_not_duplicate() {
let soul = read_template("SOUL.md");
let agents = read_template("AGENTS.md");
const SNAPSHOT: &str = "snapshots go stale";
assert!(
soul.contains(SNAPSHOT),
"SOUL.md must own the Never Assume, Verify posture"
);
assert!(
!agents.contains(SNAPSHOT),
"AGENTS.md must not duplicate the posture text, it owns the protocol"
);
assert!(
agents.contains("## Epistemic Protocol") && agents.contains("Decay:"),
"AGENTS.md must own the epistemic tracking protocol"
);
assert!(
!soul.contains("Decay:"),
"SOUL.md must not duplicate the protocol, it points at the posture only"
);
}
#[test]
fn soul_defines_a_role_not_only_a_voice() {
let soul = read_template("SOUL.md");
assert!(
soul.contains("protect the production environment")
&& soul.contains("plan before executing"),
"SOUL.md must state the operating posture (protect production, plan first), \
not just the voice. A template that defines a tone with no job ships \
personality without judgement."
);
}
#[test]
fn the_duplicate_check_is_stated_in_both_the_tool_and_the_template() {
let agents = fs::read_to_string(Path::new(TEMPLATE_DIR).join("AGENTS.md"))
.expect("AGENTS.md template must exist");
let tool = fs::read_to_string("src/brain/tools/write_opencrabs_file.rs")
.expect("write_opencrabs_file.rs must exist");
for (name, text) in [("AGENTS.md template", &agents), ("tool description", &tool)] {
assert!(
text.contains("memory_search"),
"{name} must name the tool that searches, since the agent cannot \
tell by looking"
);
assert!(
text.to_lowercase().contains("replace"),
"{name} must offer the update-in-place outcome, or the only choices \
are append and drop"
);
assert!(
text.contains("recall"),
"{name} must say per-turn recall does not substitute for the search: \
recall is keyed to the user's message, not to the line being written"
);
}
}