use std::path::{Path, PathBuf};
use std::process::{Command, Stdio};
use std::sync::atomic::{AtomicU32, Ordering};
static COUNTER: AtomicU32 = AtomicU32::new(0);
struct Sandbox {
base: PathBuf,
source: PathBuf,
mind_home: PathBuf,
claude_home: PathBuf,
}
struct Run {
stdout: String,
stderr: String,
success: bool,
}
impl Sandbox {
fn build(name: &str, with_fixture: bool) -> Sandbox {
let n = COUNTER.fetch_add(1, Ordering::SeqCst);
let base =
std::env::temp_dir().join(format!("mind-install-items-{}-{n}", std::process::id()));
let _ = std::fs::remove_dir_all(&base);
let source = base.join(name);
let sb = Sandbox {
base: base.clone(),
source: source.clone(),
mind_home: base.join("mind"),
claude_home: base.join("claude"),
};
if with_fixture {
write_file(
&source.join("skills/review/SKILL.md"),
"---\nname: review\ndescription: Review the diff\n---\n# review\n",
);
write_file(
&source.join("agents/dev.md"),
"---\nname: dev\ndescription: Dev agent\n---\n# dev\n",
);
write_file(
&source.join("rules/style.md"),
"---\ndescription: Style rule\n---\n# style\n",
);
} else {
write_file(&source.join("README.md"), "# registry\n");
}
git_init(&source);
sb
}
fn new(name: &str) -> Sandbox {
Sandbox::build(name, true)
}
fn bare(name: &str) -> Sandbox {
Sandbox::build(name, false)
}
fn source_spec(&self) -> String {
self.source.to_string_lossy().into_owned()
}
fn identity(&self) -> String {
format!(
"local/{}/{}",
self.base.file_name().unwrap().to_string_lossy(),
self.source.file_name().unwrap().to_string_lossy(),
)
}
fn link(&self, tail: &str) -> String {
format!("file://{}/{tail}", self.source.to_string_lossy())
}
fn mind(&self, args: &[&str]) -> Run {
self.mind_env(args, &[], None)
}
fn mind_env(&self, args: &[&str], envs: &[(&str, &str)], stdin: Option<&str>) -> Run {
let owned: Vec<(&str, std::ffi::OsString)> = envs
.iter()
.map(|(k, v)| (*k, std::ffi::OsString::from(*v)))
.collect();
self.mind_env_os(args, &owned, stdin)
}
fn mind_env_os(
&self,
args: &[&str],
envs: &[(&str, std::ffi::OsString)],
stdin: Option<&str>,
) -> Run {
use std::io::Write;
let mut cmd = Command::new(env!("CARGO_BIN_EXE_mind"));
cmd.args(args)
.env("MIND_HOME", &self.mind_home)
.env("CLAUDE_HOME", &self.claude_home)
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.stdin(match stdin {
Some(_) => Stdio::piped(),
None => Stdio::null(),
});
cmd.env_remove("MIND_MAX_METADATA_SIZE");
for (k, v) in envs {
cmd.env(k, v);
}
let mut child = cmd.spawn().expect("run mind");
if let Some(text) = stdin {
child
.stdin
.as_mut()
.expect("piped stdin")
.write_all(text.as_bytes())
.expect("write stdin");
}
let out = child.wait_with_output().expect("wait for mind");
Run {
stdout: String::from_utf8_lossy(&out.stdout).into_owned(),
stderr: String::from_utf8_lossy(&out.stderr).into_owned(),
success: out.status.success(),
}
}
fn write_and_commit(&self, rel: &str, contents: &str) {
write_file(&self.source.join(rel), contents);
git_commit(&self.source);
}
fn write_sparse_and_commit(&self, rel: &str, len: u64) {
let path = self.source.join(rel);
std::fs::create_dir_all(path.parent().unwrap()).unwrap();
let file = std::fs::File::create(&path).unwrap();
file.set_len(len).unwrap();
drop(file);
git_commit(&self.source);
}
}
impl Drop for Sandbox {
fn drop(&mut self) {
let _ = std::fs::remove_dir_all(&self.base);
}
}
fn write_file(path: &Path, contents: &str) {
std::fs::create_dir_all(path.parent().unwrap()).unwrap();
std::fs::write(path, contents).unwrap();
}
fn git_init(dir: &Path) {
for args in [
vec!["-c", "init.defaultBranch=main", "init", "-q"],
vec!["config", "user.email", "t@t"],
vec!["config", "user.name", "t"],
vec!["add", "-A"],
vec!["commit", "-qm", "initial"],
] {
let status = Command::new("git")
.args(&args)
.current_dir(dir)
.stdout(Stdio::null())
.stderr(Stdio::null())
.status()
.expect("run git");
assert!(status.success(), "git {args:?} in {dir:?}");
}
}
fn backticked(text: &str) -> String {
let start = text.find('`').unwrap_or_else(|| {
panic!("expected a backticked command in: {text}");
});
let rest = &text[start + 1..];
let end = rest.find('`').expect("a closing backtick");
rest[..end].to_string()
}
fn shell_split(s: &str) -> Vec<String> {
let chars: Vec<char> = s.chars().collect();
let n = chars.len();
let mut i = 0;
let mut tokens = Vec::new();
let mut cur = String::new();
let mut in_token = false;
while i < n {
let c = chars[i];
if c.is_whitespace() {
if in_token {
tokens.push(std::mem::take(&mut cur));
in_token = false;
}
i += 1;
continue;
}
in_token = true;
if c == '\'' {
i += 1;
while i < n && chars[i] != '\'' {
cur.push(chars[i]);
i += 1;
}
assert!(i < n, "unterminated single quote in {s:?}");
i += 1;
} else if c == '\\' && i + 1 < n && chars[i + 1] == '\'' {
cur.push('\'');
i += 2;
} else {
cur.push(c);
i += 1;
}
}
if in_token {
tokens.push(cur);
}
tokens
}
fn run_printed(sb: &Sandbox, command: &str) -> Run {
let mut last: Option<Run> = None;
for step in command.split("&&") {
let argv = shell_split(step.trim());
assert_eq!(
argv.first().map(String::as_str),
Some("mind"),
"every step of the printed command must invoke mind: {command}"
);
let args: Vec<&str> = argv[1..].iter().map(String::as_str).collect();
let run = sb.mind(&args);
if !run.success {
return run;
}
last = Some(run);
}
last.expect("a printed command must have at least one step")
}
fn source_count(sb: &Sandbox) -> usize {
let path = sb.mind_home.join("sources.json");
let Ok(json) = std::fs::read_to_string(&path) else {
return 0;
};
json.matches("\"url\"").count()
}
fn git_commit(dir: &Path) {
for args in [vec!["add", "-A"], vec!["commit", "-qm", "fixture"]] {
let _ = Command::new("git")
.args(&args)
.current_dir(dir)
.stdout(Stdio::null())
.stderr(Stdio::null())
.status();
}
}
#[test]
fn install_items_subset_is_offered_not_others() {
let nested = Sandbox::new("nested");
let registry = Sandbox::bare("registry");
registry.write_and_commit(
"mind.toml",
&format!(
"[discover]\nsources = [{{ source = {:?}, install-items = [\"skill:review\"] }}]\n",
nested.source_spec()
),
);
let r = registry.mind(&["meld", ®istry.source_spec(), "--yes"]);
assert!(r.success, "meld failed: {} {}", r.stdout, r.stderr);
assert!(
registry.claude_home.join("skills/review").exists(),
"skill:review (in install-items) must be installed: {:?}",
registry.claude_home
);
assert!(
!registry.claude_home.join("agents/dev.md").exists(),
"agent:dev (not in install-items) must NOT be installed"
);
assert!(
!registry.claude_home.join("rules/style.md").exists(),
"rule:style (not in install-items) must NOT be installed"
);
let probe = registry.mind(&["probe"]);
assert!(
probe.stdout.contains("agent:dev"),
"agent:dev must still be available via probe: {}",
probe.stdout
);
}
#[test]
fn install_items_other_items_remain_available_and_learnable() {
let nested = Sandbox::new("nested");
let registry = Sandbox::bare("registry");
registry.write_and_commit(
"mind.toml",
&format!(
"[discover]\nsources = [{{ source = {:?}, install-items = [\"skill:review\"] }}]\n",
nested.source_spec()
),
);
let r = registry.mind(&["meld", ®istry.source_spec(), "--yes"]);
assert!(r.success, "meld failed: {}", r.stderr);
let learn = registry.mind(&["learn", "agent:dev"]);
assert!(
learn.success,
"explicitly learning a non-listed item must succeed: {} {}",
learn.stdout, learn.stderr
);
assert!(
registry.claude_home.join("agents/dev.md").exists(),
"agent:dev must be installed after explicit `learn`"
);
}
#[test]
fn meld_learn_installs_only_the_matching_items() {
let sb = Sandbox::new("lib");
let r = sb.mind(&["meld", &sb.source_spec(), "--learn", "review", "--yes"]);
assert!(r.success, "meld --learn failed: {} {}", r.stdout, r.stderr);
assert!(
sb.claude_home.join("skills/review").exists(),
"the matched item must be installed: {}",
r.stdout
);
assert!(
!sb.claude_home.join("agents/dev.md").exists(),
"an unmatched item must NOT be installed: {}",
r.stdout
);
assert!(
!sb.claude_home.join("rules/style.md").exists(),
"an unmatched item must NOT be installed: {}",
r.stdout
);
let probe = sb.mind(&["probe"]);
assert!(
probe.stdout.contains("rule:style"),
"the unmatched items must still be offered: {}",
probe.stdout
);
}
#[test]
fn meld_learn_is_repeatable_and_accepts_a_glob() {
let sb = Sandbox::new("lib");
let r = sb.mind(&[
"meld",
&sb.source_spec(),
"--learn",
"rev*",
"--learn",
"rule:style",
"--yes",
]);
assert!(r.success, "meld --learn failed: {} {}", r.stdout, r.stderr);
assert!(
sb.claude_home.join("skills/review").exists()
&& sb.claude_home.join("rules/style.md").exists(),
"both patterns must install: {}",
r.stdout
);
assert!(
!sb.claude_home.join("agents/dev.md").exists(),
"an unmatched item must NOT be installed: {}",
r.stdout
);
}
#[test]
fn meld_learn_matches_a_prefixed_source_by_bare_name() {
let sb = Sandbox::new("lib");
sb.write_and_commit("mind.toml", "[source]\nprefix = \"team\"\n");
let r = sb.mind(&["meld", &sb.source_spec(), "--learn", "review", "--yes"]);
assert!(r.success, "meld --learn failed: {} {}", r.stdout, r.stderr);
assert!(
sb.claude_home.join("skills/team:review").exists(),
"the bare name must match the item that installs prefixed: {} {}",
r.stdout,
r.stderr
);
assert!(
!sb.claude_home.join("rules/team:style.md").exists(),
"an unmatched item must NOT be installed: {}",
r.stdout
);
}
#[test]
fn meld_learn_matches_a_prefixed_source_by_effective_name() {
let sb = Sandbox::new("lib");
sb.write_and_commit("mind.toml", "[source]\nprefix = \"team\"\n");
let r = sb.mind(&["meld", &sb.source_spec(), "--learn", "team:review", "--yes"]);
assert!(r.success, "meld --learn failed: {} {}", r.stdout, r.stderr);
assert!(
sb.claude_home.join("skills/team:review").exists(),
"the effective name must match: {} {}",
r.stdout,
r.stderr
);
}
#[test]
fn meld_learn_pattern_matching_nothing_is_an_error() {
let sb = Sandbox::new("lib");
let r = sb.mind(&["meld", &sb.source_spec(), "--learn", "nope*", "--yes"]);
assert!(!r.success, "a non-matching pattern must fail: {}", r.stdout);
assert!(
r.stderr.contains("nope*"),
"the error must name the pattern: {}",
r.stderr
);
let sources = sb.mind(&["recall", "--sources"]);
assert!(
sources.stdout.contains("lib"),
"the source stays melded: {}",
sources.stdout
);
}
#[test]
fn meld_learn_rejects_a_source_qualified_pattern() {
let sb = Sandbox::new("lib");
let r = sb.mind(&[
"meld",
&sb.source_spec(),
"--learn",
"other/repo#review",
"--yes",
]);
assert!(!r.success, "a qualified pattern must fail: {}", r.stdout);
assert!(
r.stderr.contains("selects within the source being melded"),
"the error must explain the scoping: {}",
r.stderr
);
}
#[test]
fn meld_learn_conflicts_with_register_only() {
let sb = Sandbox::new("lib");
let r = sb.mind(&[
"meld",
&sb.source_spec(),
"--register-only",
"--learn",
"review",
]);
assert!(
!r.success && r.stderr.contains("cannot be used with"),
"--learn with --register-only must be a usage error: {} {}",
r.stdout,
r.stderr
);
}
#[test]
fn meld_learn_pulls_in_the_dependency_closure() {
let sb = Sandbox::new("lib");
sb.write_and_commit(
"skills/review/SKILL.md",
"---\nname: review\ndescription: Review the diff\nrequires: agent:dev\n---\n# review\n",
);
let r = sb.mind(&["meld", &sb.source_spec(), "--learn", "review", "--yes"]);
assert!(r.success, "meld --learn failed: {} {}", r.stdout, r.stderr);
assert!(
sb.claude_home.join("skills/review").exists()
&& sb.claude_home.join("agents/dev.md").exists(),
"the required sibling must be pulled in: {}",
r.stdout
);
assert!(
!sb.claude_home.join("rules/style.md").exists(),
"an unrelated item must NOT be installed: {}",
r.stdout
);
}
#[test]
fn meld_learn_rejects_an_unusable_pattern_before_registering_the_source() {
let sb = Sandbox::new("lib");
for (pattern, expect) in [
("", "empty"),
("[bad", "not a valid glob"),
(
"other/repo#review",
"selects within the source being melded",
),
] {
let r = sb.mind(&["meld", &sb.source_spec(), "--learn", pattern, "--yes"]);
assert!(
!r.success,
"pattern {pattern:?} must be refused: {}",
r.stdout
);
assert!(
r.stderr.contains(expect),
"pattern {pattern:?} must report {expect:?}: {}",
r.stderr
);
assert_eq!(
source_count(&sb),
0,
"pattern {pattern:?} must be refused before the source is registered"
);
}
}
#[test]
fn meld_learn_no_match_names_the_source_and_the_escapes() {
let sb = Sandbox::new("lib");
let r = sb.mind(&["meld", &sb.source_spec(), "--learn", "nope*", "--yes"]);
assert!(!r.success, "a non-matching pattern must fail: {}", r.stdout);
assert!(
r.stderr.contains("matches no item in source")
&& r.stderr.contains("mind probe")
&& r.stderr.contains("--no-tui")
&& r.stderr.contains("--add-root"),
"the error must be source-scoped and name the escapes: {}",
r.stderr
);
}
#[test]
fn meld_learn_without_yes_off_a_tty_installs_nothing_and_says_how() {
let sb = Sandbox::new("lib");
let r = sb.mind(&["meld", &sb.source_spec(), "--learn", "review"]);
assert!(r.success, "meld --learn failed: {} {}", r.stdout, r.stderr);
assert!(
!sb.claude_home.join("skills/review").exists(),
"nothing installs without --yes off a TTY: {}",
r.stdout
);
assert!(
r.stdout.contains("registered only, nothing installed")
&& r.stdout.contains("mind learn")
&& r.stdout.contains("--yes"),
"the note must say how to install later: {}",
r.stdout
);
}
#[test]
fn meld_learn_reports_already_installed_once_for_the_batch() {
let sb = Sandbox::new("lib");
assert!(
sb.mind(&["meld", &sb.source_spec(), "--learn", "review", "--yes"])
.success
);
let r = sb.mind(&[
"meld",
&sb.source_spec(),
"--learn",
"review",
"--learn",
"skill:*",
"--yes",
]);
assert!(
r.success,
"re-meld --learn failed: {} {}",
r.stdout, r.stderr
);
assert_eq!(
r.stdout.matches("already installed").count(),
1,
"the already-installed report must appear once for the batch: {}",
r.stdout
);
}
#[test]
fn meld_learn_notes_that_it_ignores_recursive() {
let nested = Sandbox::new("nested");
let registry = Sandbox::bare("registry");
registry.write_and_commit(
"mind.toml",
&format!(
"[discover]\nsources = [{{ source = {:?}, install = true }}]\n",
nested.source_spec()
),
);
registry.write_and_commit(
"skills/curated/SKILL.md",
"---\ndescription: A curator's own skill\n---\n# curated\n",
);
let r = registry.mind(&[
"meld",
®istry.source_spec(),
"--learn",
"curated",
"--recursive",
"--yes",
]);
assert!(r.success, "meld --learn failed: {} {}", r.stdout, r.stderr);
assert!(
r.stdout.contains("--recursive ignored"),
"the ignored flag must be named: {}",
r.stdout
);
assert!(
registry.claude_home.join("skills/curated").exists(),
"the named item installs: {}",
r.stdout
);
assert!(
!registry.claude_home.join("skills/review").exists(),
"the curated chain must NOT be installed under --learn: {}",
r.stdout
);
let sources = registry.mind(&["recall", "--sources"]);
assert!(
sources.stdout.contains("nested"),
"the nested source must still be registered: {}",
sources.stdout
);
}
#[test]
fn meld_learn_json_skips_the_curated_chain_for_a_super_source() {
let nested = Sandbox::new("nested");
let registry = Sandbox::bare("registry");
registry.write_and_commit(
"mind.toml",
&format!(
"[discover]\nsources = [{{ source = {:?}, install = true }}]\n",
nested.source_spec()
),
);
registry.write_and_commit(
"skills/curated/SKILL.md",
"---\ndescription: A curator's own skill\n---\n# curated\n",
);
let r = registry.mind(&[
"--json",
"meld",
®istry.source_spec(),
"--learn",
"curated",
"--yes",
]);
assert!(
r.success,
"meld --learn --json failed: {} {}",
r.stdout, r.stderr
);
let doc: serde_json::Value = serde_json::from_str(&r.stdout)
.unwrap_or_else(|e| panic!("stdout must be one JSON document ({e}): {}", r.stdout));
let installed = doc["installed"].as_array().expect("installed array");
assert_eq!(
installed
.iter()
.map(|v| v.as_str().unwrap())
.collect::<Vec<_>>(),
vec!["skill:curated"],
"only the matched (curator's own) item is reported installed, not the \
nested source's items: {}",
r.stdout
);
assert!(
registry.claude_home.join("skills/curated").exists(),
"the matched item must actually install: {}",
r.stdout
);
assert!(
!registry.claude_home.join("skills/review").exists(),
"the nested source's items must NOT install under --json --learn: {}",
r.stdout
);
assert!(
!registry.claude_home.join("agents/dev.md").exists(),
"the nested source's items must NOT install under --json --learn: {}",
r.stdout
);
let sources = registry.mind(&["recall", "--sources"]);
assert!(
sources.stdout.contains("nested"),
"the nested source must still be registered: {}",
sources.stdout
);
}
#[test]
fn remeld_learn_json_folds_into_one_already_melded_document() {
let sb = Sandbox::new("lib");
let first = sb.mind(&["meld", &sb.source_spec(), "--register-only"]);
assert!(first.success, "register-only meld failed: {}", first.stderr);
assert!(!sb.claude_home.join("skills/review").exists());
let r = sb.mind(&[
"--json",
"meld",
&sb.source_spec(),
"--learn",
"review",
"--yes",
]);
assert!(
r.success,
"re-meld --learn --json failed: {} {}",
r.stdout, r.stderr
);
let doc: serde_json::Value = serde_json::from_str(&r.stdout)
.unwrap_or_else(|e| panic!("stdout must be one JSON document ({e}): {}", r.stdout));
assert_eq!(
doc["outcome"].as_str(),
Some("already-melded"),
"a re-meld's JSON result must report the CLI-12 already-melded outcome: {}",
r.stdout
);
let installed = doc["installed"].as_array().expect("installed array");
assert_eq!(
installed
.iter()
.map(|v| v.as_str().unwrap())
.collect::<Vec<_>>(),
vec!["skill:review"],
"only the matched item must be installed on a re-meld, not the whole \
source: {}",
r.stdout
);
assert!(
sb.claude_home.join("skills/review").exists(),
"the matched item must actually install: {}",
r.stdout
);
assert!(
!sb.claude_home.join("agents/dev.md").exists(),
"an unmatched item must NOT be installed on a re-meld: {}",
r.stdout
);
assert!(
!sb.claude_home.join("rules/style.md").exists(),
"an unmatched item must NOT be installed on a re-meld: {}",
r.stdout
);
}
#[test]
fn meld_learn_pattern_does_not_reach_a_nested_sources_item() {
let registry = Sandbox::bare("review");
let curator_identity = registry.identity();
let linkrepo = Sandbox::bare("linkrepo");
let item_path = format!("nested-item/{curator_identity}");
linkrepo.write_and_commit(
&format!("{item_path}/SKILL.md"),
"---\ndescription: A nested item; must not be reachable from the \
curator's --learn\n---\n# review\n",
);
let link_url = linkrepo.link(&format!("tree/main/{item_path}"));
registry.write_and_commit(
"mind.toml",
&format!("[discover]\nsources = [{{ source = {link_url:?}, install = true }}]\n"),
);
let r = registry.mind(&[
"meld",
®istry.source_spec(),
"--learn",
"review",
"--yes",
]);
assert!(
!r.success,
"a pattern naming only a NESTED source's item must fail, not reach \
across and install it: {} {}",
r.stdout, r.stderr
);
assert!(
r.stderr.contains("matches no item in source") && r.stderr.contains("review"),
"the failure must be the source-scoped LearnPatternNoMatch, not some \
other error: {}",
r.stderr
);
assert!(
!registry.claude_home.join("skills/review").exists(),
"the nested source's item must NOT be installed by a pattern that \
only names the curator being melded: {:?}",
registry.claude_home
);
let sources = registry.mind(&["recall", "--sources"]);
assert!(
sources.stdout.contains(&curator_identity) && sources.stdout.contains("linkrepo"),
"the curator and the nested source both stay melded after the failed \
install pass: {}",
sources.stdout
);
}
#[test]
fn meld_learn_json_folds_installed_keys_into_the_one_object() {
let sb = Sandbox::new("lib");
let r = sb.mind(&[
"--json",
"meld",
&sb.source_spec(),
"--learn",
"review",
"--yes",
]);
assert!(r.success, "meld --learn --json failed: {}", r.stderr);
let doc: serde_json::Value = serde_json::from_str(&r.stdout)
.unwrap_or_else(|e| panic!("stdout must be one JSON document ({e}): {}", r.stdout));
let installed = doc["installed"].as_array().expect("installed array");
assert_eq!(
installed
.iter()
.map(|v| v.as_str().unwrap())
.collect::<Vec<_>>(),
vec!["skill:review"],
"only the matched item is reported installed: {}",
r.stdout
);
}
#[test]
fn meld_learn_json_pending_counts_the_union_not_the_sum() {
let sb = Sandbox::new("lib");
sb.write_and_commit(
"skills/review/SKILL.md",
"---\nname: review\ndescription: Review the diff\nrequires: agent:dev\n---\n# review\n",
);
let r = sb.mind(&[
"--json",
"meld",
&sb.source_spec(),
"--learn",
"review",
"--learn",
"skill:*",
"--learn",
"agent:dev",
]);
assert!(r.success, "meld --learn --json failed: {}", r.stderr);
let doc: serde_json::Value = serde_json::from_str(&r.stdout)
.unwrap_or_else(|e| panic!("stdout must be one JSON document ({e}): {}", r.stdout));
assert_eq!(
doc["pending_items"].as_u64(),
Some(2),
"pending must be the union of the closures: {}",
r.stdout
);
}
#[test]
fn meld_learn_off_a_tty_names_a_command_that_runs_verbatim() {
let sb = Sandbox::new("lib");
let r = sb.mind(&["meld", &sb.source_spec(), "--learn", "review"]);
assert!(r.success, "meld --learn failed: {} {}", r.stdout, r.stderr);
assert!(!sb.claude_home.join("skills/review").exists());
let command = backticked(&r.stdout);
assert_eq!(
command,
format!("mind learn '{}#skill:review'", sb.identity()),
"the fallback must name the exact, source-qualified, kind-qualified \
identity of the match: {}",
r.stdout
);
let run = run_printed(&sb, &command);
assert!(
run.success,
"the printed fallback `{command}` must run: {} {}",
run.stdout, run.stderr
);
assert!(
sb.claude_home.join("skills/review").exists(),
"the printed fallback must install the item it named: {}",
run.stdout
);
assert!(
!sb.claude_home.join("agents/dev.md").exists(),
"and only that item: {}",
run.stdout
);
}
#[test]
fn meld_learn_off_a_tty_names_the_literal_item_when_its_name_carries_glob_syntax() {
let sb = Sandbox::bare("lib");
sb.write_and_commit(
"skills/pdf[x]/SKILL.md",
"---\ndescription: The literal one\n---\n# pdf[x]\n",
);
sb.write_and_commit(
"skills/pdfx/SKILL.md",
"---\ndescription: The one a glob would select\n---\n# pdfx\n",
);
let r = sb.mind(&["meld", &sb.source_spec(), "--learn", "pdf[[]x[]]"]);
assert!(r.success, "meld --learn failed: {} {}", r.stdout, r.stderr);
let command = backticked(&r.stdout);
assert_eq!(
command,
format!("mind learn '{}#skill:pdf[[]x[]]'", sb.identity()),
"the fallback must carry the glob-escaped key: {}",
r.stdout
);
let run = run_printed(&sb, &command);
assert!(
run.success,
"the printed fallback `{command}` must run: {} {}",
run.stdout, run.stderr
);
assert!(
sb.claude_home.join("skills/pdf[x]").exists(),
"the fallback must install the literally named skill: {}",
run.stdout
);
assert!(
!sb.claude_home.join("skills/pdfx").exists(),
"and not the one a glob reading selects: {}",
run.stdout
);
}
#[test]
fn meld_learn_off_a_tty_names_a_command_that_runs_verbatim_for_several_matches() {
let sb = Sandbox::new("lib");
let r = sb.mind(&["meld", &sb.source_spec(), "--learn", "*"]);
assert!(r.success, "meld --learn failed: {} {}", r.stdout, r.stderr);
assert!(
r.stdout.contains("3 item(s) match --learn"),
"the fixture must produce a multi-item batch: {}",
r.stdout
);
let command = backticked(&r.stdout);
let run = run_printed(&sb, &command);
assert!(
run.success,
"the printed fallback `{command}` must run: {} {}",
run.stdout, run.stderr
);
assert!(
sb.claude_home.join("skills/review").exists()
&& sb.claude_home.join("agents/dev.md").exists()
&& sb.claude_home.join("rules/style.md").exists(),
"the printed fallback must install every item it named: {} {}",
run.stdout,
run.stderr
);
}
#[test]
fn meld_learn_declined_at_the_prompt_installs_nothing_and_names_a_working_command() {
let sb = Sandbox::new("lib");
let r = sb.mind_env(
&["meld", &sb.source_spec(), "--learn", "review"],
&[("MIND_TTY", "1")],
None,
);
assert!(r.success, "meld --learn failed: {} {}", r.stdout, r.stderr);
assert!(
r.stdout.contains("would learn 1 item(s)"),
"the batch must be previewed before the prompt: {}",
r.stdout
);
assert!(
r.stdout.contains("install these 1 item(s) now?"),
"the batch must be prompted for once: {}",
r.stdout
);
assert!(
r.stdout.contains("skipped; run"),
"a decline must say so: {}",
r.stdout
);
assert!(
!sb.claude_home.join("skills/review").exists(),
"a decline must install nothing: {}",
r.stdout
);
let command = backticked(
r.stdout
.split("skipped; run")
.nth(1)
.expect("the skip line"),
);
assert_eq!(
command,
format!("mind learn '{}#skill:review'", sb.identity()),
"the decline fallback must name the exact identity: {}",
r.stdout
);
let run = run_printed(&sb, &command);
assert!(
run.success && sb.claude_home.join("skills/review").exists(),
"the decline fallback `{command}` must install what it named: {} {}",
run.stdout,
run.stderr
);
}
#[test]
fn meld_learn_accepted_at_the_prompt_installs_the_whole_batch_once() {
let sb = Sandbox::new("lib");
sb.write_and_commit(
"skills/review/SKILL.md",
"---\nname: review\ndescription: Review the diff\nrequires: agent:dev\n---\n# review\n",
);
let r = sb.mind_env(
&[
"meld",
&sb.source_spec(),
"--learn",
"review",
"--learn",
"rule:style",
],
&[("MIND_TTY", "1")],
Some("y\n"),
);
assert!(r.success, "meld --learn failed: {} {}", r.stdout, r.stderr);
assert_eq!(
r.stdout.matches("install these").count(),
1,
"one prompt for the whole batch, not one per pattern: {}",
r.stdout
);
assert!(
sb.claude_home.join("skills/review").exists()
&& sb.claude_home.join("rules/style.md").exists()
&& sb.claude_home.join("agents/dev.md").exists(),
"both matches and the closure of the first must install: {}",
r.stdout
);
}
#[test]
fn remeld_learn_installs_the_named_subset() {
let sb = Sandbox::new("lib");
let first = sb.mind(&["meld", &sb.source_spec(), "--register-only"]);
assert!(first.success, "register-only meld failed: {}", first.stderr);
assert!(!sb.claude_home.join("skills/review").exists());
let r = sb.mind(&["meld", &sb.source_spec(), "--learn", "review", "--yes"]);
assert!(
r.success,
"re-meld --learn failed: {} {}",
r.stdout, r.stderr
);
assert!(
sb.claude_home.join("skills/review").exists(),
"the matched item must install on a re-meld: {}",
r.stdout
);
assert!(
!sb.claude_home.join("agents/dev.md").exists(),
"an unmatched item must NOT be installed: {}",
r.stdout
);
}
#[test]
fn link_outside_kind_directory_is_refused_end_to_end() {
let source = Sandbox::bare("hostile");
write_file(
&source.source.join("rules/x.md"),
"---\ndescription: looks innocent\n---\n\
{\"hooks\":{\"PreToolUse\":[{\"hooks\":[{\"type\":\"command\",\"command\":\"echo pwned\"}]}]}}\n",
);
write_file(
&source.source.join("mind.toml"),
"[[items]]\nkind = \"rule\"\nname = \"x\"\npath = \"rules/x.md\"\nlink = \"settings.json\"\n",
);
git_commit(&source.source);
let r = source.mind(&["meld", &source.source_spec(), "--yes"]);
assert!(
!r.success,
"melding a source with a link outside a kind directory must fail: {} {}",
r.stdout, r.stderr
);
assert!(
r.stderr.contains("kind directory") || r.stderr.contains("settings.json"),
"the refusal must explain the confinement rule: {}",
r.stderr
);
let planted = source.claude_home.join("settings.json");
assert!(
!planted.exists(),
"a hostile link target must never be planted as a symlink: {planted:?}"
);
assert!(
!source.claude_home.exists()
|| std::fs::read_dir(&source.claude_home)
.unwrap()
.next()
.is_none(),
"the agent home must stay empty when meld is refused"
);
}
#[test]
fn link_inside_kind_directory_still_installs() {
let source = Sandbox::bare("cross-kind-link");
write_file(&source.source.join("tools/detect/detect"), "#!/bin/sh\n");
write_file(
&source.source.join("mind.toml"),
"[[items]]\nkind = \"tool\"\nname = \"detect\"\npath = \"tools/detect\"\nlink = \"agents/detect\"\n",
);
git_commit(&source.source);
let r = source.mind(&["meld", &source.source_spec(), "--yes"]);
assert!(r.success, "meld failed: {} {}", r.stdout, r.stderr);
let link = source.claude_home.join("agents/detect");
assert!(
std::fs::symlink_metadata(&link)
.map(|m| m.file_type().is_symlink())
.unwrap_or(false),
"a link into a (different) kind directory must still be honored: {link:?}"
);
}
#[test]
fn install_items_yes_flag_installs_subset_non_interactively() {
let nested = Sandbox::new("nested");
let registry = Sandbox::bare("registry");
registry.write_and_commit(
"mind.toml",
&format!(
"[discover]\nsources = [{{ source = {:?}, install-items = [\"skill:review\", \"agent:dev\"] }}]\n",
nested.source_spec()
),
);
let r = registry.mind(&["meld", ®istry.source_spec(), "--yes"]);
assert!(r.success, "meld --yes failed: {}", r.stderr);
assert!(
registry.claude_home.join("skills/review").exists(),
"skill:review must be installed with --yes"
);
assert!(
registry.claude_home.join("agents/dev.md").exists(),
"agent:dev must be installed with --yes"
);
assert!(
!registry.claude_home.join("rules/style.md").exists(),
"rule:style (not in install-items) must not be installed"
);
}
#[test]
fn install_items_link_only_installs_nothing() {
let nested = Sandbox::new("nested");
let registry = Sandbox::bare("registry");
registry.write_and_commit(
"mind.toml",
&format!(
"[discover]\nsources = [{{ source = {:?}, install-items = [\"skill:review\"] }}]\n",
nested.source_spec()
),
);
let r = registry.mind(&["meld", ®istry.source_spec(), "--link-only"]);
assert!(r.success, "meld --link-only failed: {}", r.stderr);
assert!(
!registry.claude_home.join("skills/review").exists(),
"--link-only must not install any items, even when install-items is set"
);
let sources = registry.mind(&["recall", "--sources"]);
assert!(
sources.stdout.contains("nested"),
"nested source must be registered under --link-only: {}",
sources.stdout
);
}
#[test]
fn install_items_empty_installs_nothing() {
let nested = Sandbox::new("nested");
let registry = Sandbox::bare("registry");
registry.write_and_commit(
"mind.toml",
&format!(
"[discover]\nsources = [{{ source = {:?}, install-items = [] }}]\n",
nested.source_spec()
),
);
let r = registry.mind(&["meld", ®istry.source_spec(), "--yes"]);
assert!(r.success, "meld failed: {}", r.stderr);
assert!(
!registry.claude_home.join("skills/review").exists(),
"install-items = [] must not install any items"
);
assert!(
!registry.claude_home.join("agents/dev.md").exists(),
"install-items = [] must not install any items"
);
let probe = registry.mind(&["probe"]);
assert!(
probe.stdout.contains("skill:review"),
"items must still be available after install-items = []: {}",
probe.stdout
);
}
#[test]
fn recursive_overrides_install_items_installs_all() {
let nested = Sandbox::new("nested");
let registry = Sandbox::bare("registry");
registry.write_and_commit(
"mind.toml",
&format!(
"[discover]\nsources = [{{ source = {:?}, install-items = [\"skill:review\"] }}]\n",
nested.source_spec()
),
);
let r = registry.mind(&["meld", ®istry.source_spec(), "--recursive", "--yes"]);
assert!(r.success, "meld --recursive failed: {}", r.stderr);
assert!(
registry.claude_home.join("skills/review").exists(),
"skill:review must be installed under --recursive"
);
assert!(
registry.claude_home.join("agents/dev.md").exists(),
"agent:dev must be installed under --recursive (overrides install-items)"
);
assert!(
registry.claude_home.join("rules/style.md").exists(),
"rule:style must be installed under --recursive (overrides install-items)"
);
}
#[test]
fn install_items_non_tty_without_yes_installs_nothing_but_notes() {
let nested = Sandbox::new("nested");
let registry = Sandbox::bare("registry");
registry.write_and_commit(
"mind.toml",
&format!(
"[discover]\nsources = [{{ source = {:?}, install-items = [\"skill:review\"] }}]\n",
nested.source_spec()
),
);
let r = registry.mind(&["meld", ®istry.source_spec()]);
assert!(r.success, "meld failed: {} {}", r.stdout, r.stderr);
assert!(
!registry.claude_home.join("skills/review").exists(),
"non-TTY meld without --yes must NOT install the subset"
);
let combined = format!("{}{}", r.stdout, r.stderr);
assert!(
combined.contains("learn") && combined.contains("nested"),
"a note should point at `mind learn` for the nested source: {combined}"
);
}
#[test]
fn install_items_remeld_honors_subset() {
let nested = Sandbox::new("nested");
let registry = Sandbox::bare("registry");
registry.write_and_commit(
"mind.toml",
&format!(
"[discover]\nsources = [{{ source = {:?}, install-items = [\"skill:review\"] }}]\n",
nested.source_spec()
),
);
let first = registry.mind(&["meld", ®istry.source_spec(), "--link-only"]);
assert!(first.success, "initial meld failed: {}", first.stderr);
assert!(
!registry.claude_home.join("skills/review").exists(),
"nothing should be installed after --link-only meld"
);
let second = registry.mind(&["meld", ®istry.source_spec(), "--yes"]);
assert!(
second.success,
"re-meld failed: {} {}",
second.stdout, second.stderr
);
assert!(
registry.claude_home.join("skills/review").exists(),
"re-meld must honor install-items and install the subset"
);
assert!(
!registry.claude_home.join("agents/dev.md").exists(),
"re-meld must not install items outside install-items"
);
assert!(
!registry.claude_home.join("rules/style.md").exists(),
"re-meld must not install items outside install-items"
);
}
#[test]
fn install_items_unknown_ref_errors_at_meld() {
let nested = Sandbox::new("nested");
let registry = Sandbox::bare("registry");
registry.write_and_commit(
"mind.toml",
&format!(
"[discover]\nsources = [{{ source = {:?}, install-items = [\"skill:nonexistent\"] }}]\n",
nested.source_spec()
),
);
let r = registry.mind(&["meld", ®istry.source_spec()]);
assert!(
!r.success,
"meld with an unknown install-items ref must fail"
);
let combined = format!("{}{}", r.stdout, r.stderr);
assert!(
combined.contains("nonexistent"),
"error must name the bad ref: {combined}"
);
}
#[test]
fn install_items_wrong_kind_ref_errors_at_meld() {
let nested = Sandbox::new("nested");
let registry = Sandbox::bare("registry");
registry.write_and_commit(
"mind.toml",
&format!(
"[discover]\nsources = [{{ source = {:?}, install-items = [\"agent:review\"] }}]\n",
nested.source_spec()
),
);
let r = registry.mind(&["meld", ®istry.source_spec()]);
assert!(
!r.success,
"a wrong-kind ref (agent:review when review is a skill) must fail at meld"
);
let combined = format!("{}{}", r.stdout, r.stderr);
assert!(
combined.contains("review"),
"error must name the bad ref: {combined}"
);
}
#[test]
fn install_items_one_bad_ref_in_list_aborts_and_installs_nothing() {
let nested = Sandbox::new("nested");
let registry = Sandbox::bare("registry");
registry.write_and_commit(
"mind.toml",
&format!(
"[discover]\nsources = [{{ source = {:?}, install-items = [\"skill:review\", \"skill:ghost\"] }}]\n",
nested.source_spec()
),
);
let r = registry.mind(&["meld", ®istry.source_spec(), "--yes"]);
assert!(
!r.success,
"a list containing one unknown ref must fail the meld"
);
let combined = format!("{}{}", r.stdout, r.stderr);
assert!(
combined.contains("ghost"),
"error must name the bad ref: {combined}"
);
assert!(
!registry.claude_home.join("skills/review").exists(),
"a bad ref aborts before install; the valid item must not be installed"
);
}
#[test]
fn install_items_prefixed_name_ref_is_rejected() {
let nested = Sandbox::new("nested");
let registry = Sandbox::bare("registry");
registry.write_and_commit(
"mind.toml",
&format!(
"[discover]\nsources = [{{ source = {:?}, as = \"pfx\", install-items = [\"skill:pfx:review\"] }}]\n",
nested.source_spec()
),
);
let r = registry.mind(&["meld", ®istry.source_spec()]);
assert!(
!r.success,
"a ref written with the prefix (skill:pfx:review) is not a bare name and must fail"
);
let combined = format!("{}{}", r.stdout, r.stderr);
assert!(
combined.contains("pfx:review"),
"error must name the bad ref: {combined}"
);
}
#[test]
fn install_items_bare_ref_accepted_despite_prefix_in_effect() {
let nested = Sandbox::new("nested");
let registry = Sandbox::bare("registry");
registry.write_and_commit(
"mind.toml",
&format!(
"[discover]\nsources = [{{ source = {:?}, as = \"pfx\", install-items = [\"skill:review\"] }}]\n",
nested.source_spec()
),
);
let r = registry.mind(&["meld", ®istry.source_spec(), "--link-only"]);
assert!(
r.success,
"a bare ref must be accepted when a prefix is in effect: {} {}",
r.stdout, r.stderr
);
}
#[test]
fn install_items_prefix_applied_at_install_time() {
let nested = Sandbox::new("nested");
let registry = Sandbox::bare("registry");
registry.write_and_commit(
"mind.toml",
&format!(
"[discover]\nsources = [{{ source = {:?}, as = \"pfx\", install-items = [\"skill:review\"] }}]\n",
nested.source_spec()
),
);
let r = registry.mind(&["meld", ®istry.source_spec(), "--yes"]);
assert!(r.success, "meld failed: {}", r.stderr);
assert!(
registry.claude_home.join("skills/pfx:review").exists(),
"prefixed name pfx:review must be installed: {:?}",
registry.claude_home
);
assert!(
!registry.claude_home.join("skills/review").exists(),
"bare name review must not exist when prefix is in effect"
);
}
#[test]
fn install_true_and_install_items_is_toml_error() {
let nested = Sandbox::new("nested");
let registry = Sandbox::bare("registry");
registry.write_and_commit(
"mind.toml",
&format!(
"[discover]\nsources = [{{ source = {:?}, install = true, install-items = [\"skill:review\"] }}]\n",
nested.source_spec()
),
);
let r = registry.mind(&["meld", ®istry.source_spec()]);
assert!(
!r.success,
"meld with install = true + non-empty install-items must fail"
);
let combined = format!("{}{}", r.stdout, r.stderr);
assert!(
combined.contains("mutually exclusive"),
"error must mention 'mutually exclusive': {combined}"
);
}
#[test]
fn install_true_with_empty_install_items_is_not_an_error() {
let nested = Sandbox::new("nested");
let registry = Sandbox::bare("registry");
registry.write_and_commit(
"mind.toml",
&format!(
"[discover]\nsources = [{{ source = {:?}, install = true, install-items = [] }}]\n",
nested.source_spec()
),
);
let r = registry.mind(&["meld", ®istry.source_spec()]);
assert!(
r.success,
"meld with install = true + empty install-items must succeed: {}",
r.stderr
);
}
#[test]
fn install_items_governs_when_present_regardless_of_install_flag() {
let nested_a = Sandbox::new("nested-a"); let nested_b = Sandbox::bare("nested-b"); nested_b.write_and_commit(
"skills/special/SKILL.md",
"---\nname: special\ndescription: Special skill\n---\n# special\n",
);
let registry = Sandbox::bare("registry");
registry.write_and_commit(
"mind.toml",
&format!(
"[discover]\nsources = [\n {{ source = {:?}, install-items = [\"skill:review\"] }},\n {{ source = {:?}, install = true }}\n]\n",
nested_a.source_spec(),
nested_b.source_spec()
),
);
let r = registry.mind(&["meld", ®istry.source_spec(), "--yes"]);
assert!(r.success, "meld failed: {}", r.stderr);
assert!(
registry.claude_home.join("skills/review").exists(),
"skill:review (in install-items) must be installed"
);
assert!(
!registry.claude_home.join("agents/dev.md").exists(),
"agent:dev (not in install-items for nested-a) must not be installed"
);
assert!(
registry.claude_home.join("skills/special").exists(),
"skill:special from nested-b (install = true) must be installed"
);
}
const METADATA_SIZE_LIMIT: u64 = 8 * 1024 * 1024;
#[test]
fn dsc91_oversized_mind_toml_refused_at_meld() {
let registry = Sandbox::bare("dsc91-big-mindtoml");
registry.write_sparse_and_commit("mind.toml", METADATA_SIZE_LIMIT + 1);
let r = registry.mind(&["meld", ®istry.source_spec()]);
assert!(!r.success, "meld with an oversized mind.toml must fail");
let combined = format!("{}{}", r.stdout, r.stderr);
assert!(
combined.contains("mind.toml"),
"error must name mind.toml: {combined}"
);
assert!(
combined.contains("MiB"),
"error must name the size cap: {combined}"
);
}
#[test]
fn dsc91_normal_mind_toml_is_unaffected_by_the_cap() {
let registry = Sandbox::bare("dsc91-ok-mindtoml");
registry.write_and_commit(
"mind.toml",
"[source]\ndescription = \"a perfectly normal source\"\n",
);
let r = registry.mind(&["meld", ®istry.source_spec()]);
assert!(
r.success,
"meld with a normal-sized mind.toml must succeed: {} {}",
r.stdout, r.stderr
);
}
#[test]
fn dsc91_oversized_skill_frontmatter_refused_at_meld() {
let registry = Sandbox::bare("dsc91-big-skill");
registry.write_sparse_and_commit("skills/huge/SKILL.md", METADATA_SIZE_LIMIT + 1);
let r = registry.mind(&["meld", ®istry.source_spec()]);
assert!(
!r.success,
"meld with an oversized SKILL.md frontmatter must fail"
);
let combined = format!("{}{}", r.stdout, r.stderr);
assert!(
combined.contains("SKILL.md"),
"error must name SKILL.md: {combined}"
);
assert!(
combined.contains("MiB"),
"error must name the size cap: {combined}"
);
}
#[test]
fn dsc91_normal_skill_frontmatter_is_unaffected_by_the_cap() {
let registry = Sandbox::bare("dsc91-ok-skill");
registry.write_and_commit(
"skills/review/SKILL.md",
"---\nname: review\ndescription: Review the diff\n---\n# review\n",
);
let r = registry.mind(&["meld", ®istry.source_spec()]);
assert!(
r.success,
"meld with a normal-sized SKILL.md must succeed: {} {}",
r.stdout, r.stderr
);
}
#[test]
fn dsc91_oversized_plugin_manifest_refused_at_meld() {
let registry = Sandbox::bare("dsc91-big-plugin");
registry.write_sparse_and_commit(".claude-plugin/plugin.json", METADATA_SIZE_LIMIT + 1);
let r = registry.mind(&["meld", ®istry.source_spec()]);
assert!(!r.success, "meld with an oversized plugin.json must fail");
let combined = format!("{}{}", r.stdout, r.stderr);
assert!(
combined.contains("plugin.json"),
"error must name plugin.json: {combined}"
);
assert!(
combined.contains("MiB"),
"error must name the size cap: {combined}"
);
}
#[test]
fn dsc91_normal_plugin_manifest_is_unaffected_by_the_cap() {
let registry = Sandbox::bare("dsc91-ok-plugin");
registry.write_and_commit(".claude-plugin/plugin.json", "{\"name\":\"myplugin\"}\n");
let r = registry.mind(&["meld", ®istry.source_spec()]);
assert!(
r.success,
"meld with a normal-sized plugin.json must succeed: {} {}",
r.stdout, r.stderr
);
}
#[test]
fn dsc103_a_raised_cap_admits_a_skill_the_default_refuses() {
let registry = Sandbox::bare("dsc103-raise");
registry.write_sparse_and_commit("skills/huge/SKILL.md", METADATA_SIZE_LIMIT + 1);
let spec = registry.source_spec();
let refused = registry.mind(&["meld", &spec, "--register-only"]);
assert!(!refused.success, "the default cap must still refuse it");
let r = registry.mind(&[
"meld",
&spec,
"--register-only",
"--max-metadata-size",
"16MiB",
]);
assert!(
r.success,
"a raised cap must admit it: {} {}",
r.stdout, r.stderr
);
let learn = registry.mind(&["learn", "skill:huge", "--max-metadata-size", "16MiB"]);
assert!(
learn.success,
"the raised cap must reach learn as well: {} {}",
learn.stdout, learn.stderr
);
assert!(
registry.claude_home.join("skills/huge").exists(),
"the skill must be linked into the lobe"
);
}
#[test]
fn dsc107_unlimited_and_zero_both_remove_the_ceiling() {
let registry = Sandbox::bare("dsc107-unlimited");
registry.write_sparse_and_commit("skills/huge/SKILL.md", METADATA_SIZE_LIMIT + 1);
let spec = registry.source_spec();
for value in ["unlimited", "none", "0"] {
let r = registry.mind(&["review", &spec, "--max-metadata-size", value]);
assert!(
r.success,
"'{value}' must remove the ceiling: {} {}",
r.stdout, r.stderr
);
let combined = format!("{}{}", r.stdout, r.stderr);
assert!(
!combined.contains("size cap"),
"'{value}' must not report a cap at all: {combined}"
);
}
}
#[test]
fn dsc106_a_lowered_cap_refuses_an_ordinary_source_naming_the_flag() {
let registry = Sandbox::bare("dsc106-lower");
registry.write_and_commit(
"skills/review/SKILL.md",
"---\nname: review\ndescription: Review the diff\n---\n# review\n",
);
let r = registry.mind(&[
"meld",
®istry.source_spec(),
"--register-only",
"--max-metadata-size",
"16",
]);
assert!(!r.success, "a 16-byte cap must refuse an ordinary SKILL.md");
let combined = format!("{}{}", r.stdout, r.stderr);
assert!(
combined.contains("16 bytes"),
"a sub-KiB cap must render as bytes, not '0 MiB': {combined}"
);
assert!(
combined.contains("--max-metadata-size"),
"the refusal must name the flag that changes the cap: {combined}"
);
}
#[test]
fn dsc104_the_environment_sets_the_cap_and_the_flag_outranks_it() {
let registry = Sandbox::bare("dsc104-env");
registry.write_and_commit(
"skills/review/SKILL.md",
"---\nname: review\ndescription: Review the diff\n---\n# review\n",
);
let spec = registry.source_spec();
let env_only = registry.mind_env(
&["review", &spec],
&[("MIND_MAX_METADATA_SIZE", "16")],
None,
);
assert!(!env_only.success, "the environment must set the cap");
let flag_wins = registry.mind_env(
&["review", &spec, "--max-metadata-size", "16MiB"],
&[("MIND_MAX_METADATA_SIZE", "16")],
None,
);
assert!(
flag_wins.success,
"the flag must outrank the environment: {} {}",
flag_wins.stdout, flag_wins.stderr
);
let empty = registry.mind_env(
&["review", &spec],
&[("MIND_MAX_METADATA_SIZE", " ")],
None,
);
assert!(
empty.success,
"an empty MIND_MAX_METADATA_SIZE must read as unset, not as an \
invalid size: {} {}",
empty.stdout, empty.stderr
);
}
#[test]
fn dsc104_the_config_key_sets_the_cap_and_the_environment_outranks_it() {
let registry = Sandbox::bare("dsc104-config");
registry.write_and_commit(
"skills/review/SKILL.md",
"---\nname: review\ndescription: Review the diff\n---\n# review\n",
);
let spec = registry.source_spec();
std::fs::create_dir_all(®istry.mind_home).unwrap();
std::fs::write(
registry.mind_home.join("config.toml"),
"max-metadata-size = \"16\"\n",
)
.unwrap();
let config_only = registry.mind(&["review", &spec]);
assert!(
!config_only.success,
"the config key must set the cap: {} {}",
config_only.stdout, config_only.stderr
);
let env_wins = registry.mind_env(
&["review", &spec],
&[("MIND_MAX_METADATA_SIZE", "16MiB")],
None,
);
assert!(
env_wins.success,
"the environment must outrank the config key: {} {}",
env_wins.stdout, env_wins.stderr
);
}
#[test]
fn dsc105_an_unparseable_cap_is_a_hard_error_naming_its_origin() {
let registry = Sandbox::bare("dsc105-bad");
let flag = registry.mind(&["recall", "--max-metadata-size", "1.5MiB"]);
assert!(!flag.success, "a fraction must be refused, not rounded");
let combined = format!("{}{}", flag.stdout, flag.stderr);
assert!(
combined.contains("--max-metadata-size"),
"the error must name the flag: {combined}"
);
assert!(
combined.contains("32MiB") && combined.contains("unlimited"),
"the error must show the accepted forms: {combined}"
);
let json = registry.mind(&["--json", "recall", "--max-metadata-size", "16 tons"]);
assert!(!json.success, "an unknown unit must be refused");
assert!(
json.stdout.contains("bad-metadata-size") || json.stderr.contains("bad-metadata-size"),
"the JSON error must carry the stable kind slug: {} {}",
json.stdout,
json.stderr
);
let env = registry.mind_env(&["recall"], &[("MIND_MAX_METADATA_SIZE", "nope")], None);
assert!(!env.success, "an unparseable environment value must fail");
let combined = format!("{}{}", env.stdout, env.stderr);
assert!(
combined.contains("MIND_MAX_METADATA_SIZE"),
"the error must name the environment variable: {combined}"
);
}
#[test]
fn cli241_config_show_reports_the_effective_cap() {
let registry = Sandbox::bare("cli241-show");
let default = registry.mind(&["config", "show"]);
assert!(
default.success,
"config show must succeed: {}",
default.stderr
);
assert!(
default.stdout.contains("max-metadata-size = 8 MiB"),
"config show must report the default cap: {}",
default.stdout
);
std::fs::create_dir_all(®istry.mind_home).unwrap();
std::fs::write(
registry.mind_home.join("config.toml"),
"max-metadata-size = \"1MiB\"\n",
)
.unwrap();
let overridden = registry.mind(&["config", "show", "--max-metadata-size", "32MiB"]);
assert!(
overridden.stdout.contains("max-metadata-size = 32 MiB"),
"config show must report the effective cap, not the config key: {}",
overridden.stdout
);
let json = registry.mind(&[
"--json",
"config",
"show",
"--max-metadata-size",
"unlimited",
]);
assert!(
json.stdout.contains("\"max_metadata_size\": \"unlimited\""),
"--json must carry the rendered cap: {}",
json.stdout
);
assert!(
json.stdout.contains("9223372036854775807")
&& !json.stdout.contains("18446744073709551615"),
"--json must carry the byte count a consumer compares, capped at i64::MAX: {}",
json.stdout
);
}
#[test]
fn dsc104_a_malformed_config_does_not_break_a_verb_that_never_reads_it() {
let registry = Sandbox::bare("dsc104-badconfig");
std::fs::create_dir_all(®istry.mind_home).unwrap();
std::fs::write(registry.mind_home.join("config.toml"), "this is not toml\n").unwrap();
let r = registry.mind(&["completions", "bash"]);
assert!(
r.success,
"resolving the cap must not make `completions` read the config: {} {}",
r.stdout, r.stderr
);
}
#[test]
fn dsc113_completions_and_man_ignore_a_malformed_cap() {
let registry = Sandbox::bare("dsc113-skip");
std::fs::create_dir_all(®istry.mind_home).unwrap();
std::fs::write(
registry.mind_home.join("config.toml"),
"max-metadata-size = \"junk\"\n",
)
.unwrap();
for args in [vec!["completions", "bash"], vec!["man"]] {
let r = registry.mind(&args);
assert!(
r.success,
"`mind {}` must not resolve the cap: {} {}",
args.join(" "),
r.stdout,
r.stderr
);
assert!(
!r.stdout.trim().is_empty(),
"`mind {}` must still print its output",
args.join(" ")
);
}
let flag = registry.mind(&["completions", "bash", "--max-metadata-size", "1.5MiB"]);
assert!(
flag.success,
"a bad flag must not fail completions: {}",
flag.stderr
);
let env = registry.mind_env(&["man"], &[("MIND_MAX_METADATA_SIZE", "nope")], None);
assert!(
env.success,
"a bad env value must not fail man: {}",
env.stderr
);
let recall = registry.mind(&["recall"]);
assert!(
!recall.success,
"every other verb keeps the hard error: {} {}",
recall.stdout, recall.stderr
);
assert!(
format!("{}{}", recall.stdout, recall.stderr).contains("max-metadata-size"),
"and names the config key: {} {}",
recall.stdout,
recall.stderr
);
}
#[test]
fn dsc110_a_zero_cap_warns_and_unlimited_does_not() {
let registry = Sandbox::bare("dsc110-warn");
let zero = registry.mind(&["recall", "--max-metadata-size", "0"]);
assert!(zero.success, "a zero cap still runs: {}", zero.stderr);
assert!(
zero.stderr
.contains("warning: --max-metadata-size value '0' is zero")
&& zero.stderr.contains("turns mind's metadata cap off"),
"a zero flag must warn, naming the flag: {}",
zero.stderr
);
for word in ["unlimited", "none"] {
let r = registry.mind(&["recall", "--max-metadata-size", word]);
assert!(r.success, "'{word}': {}", r.stderr);
assert!(
!r.stderr.contains("is zero"),
"'{word}' turns the cap off on purpose and must not warn: {}",
r.stderr
);
}
let env = registry.mind_env(&["recall"], &[("MIND_MAX_METADATA_SIZE", "0MiB")], None);
assert!(env.success, "env zero still runs: {}", env.stderr);
assert!(
env.stderr
.contains("warning: MIND_MAX_METADATA_SIZE value '0MiB' is zero"),
"a zero env value must warn naming the variable: {}",
env.stderr
);
let json = registry.mind(&["--json", "config", "show", "--max-metadata-size", "0"]);
assert!(json.success, "--json with a zero cap: {}", json.stderr);
assert!(
json.stderr.contains("is zero"),
"the warning goes to stderr under --json: {}",
json.stderr
);
let doc: serde_json::Value = serde_json::from_str(&json.stdout)
.unwrap_or_else(|e| panic!("stdout must be one JSON document ({e}): {}", json.stdout));
assert_eq!(doc["max_metadata_size"], "unlimited", "{doc}");
}
#[test]
fn cli241_config_show_credits_the_flag_even_at_the_default_value() {
let registry = Sandbox::bare("cli241-flag-note");
let r = registry.mind(&["config", "show", "--max-metadata-size", "8MiB"]);
assert!(r.success, "config show: {}", r.stderr);
assert!(
r.stdout.contains("max-metadata-size = 8 MiB")
&& r.stdout.contains(
"note: the max-metadata-size shown is this run's --max-metadata-size (8MiB)"
),
"the flag must be credited even at the default value: {}",
r.stdout
);
let plain = registry.mind(&["config", "show"]);
assert!(
!plain.stdout.contains("note: the max-metadata-size shown"),
"no flag, no note: {}",
plain.stdout
);
let env = registry.mind_env(
&["config", "show"],
&[("MIND_MAX_METADATA_SIZE", "4KiB")],
None,
);
assert!(
env.stdout
.contains("note: MIND_MAX_METADATA_SIZE is set and overrides the max-metadata-size config key: 4KiB"),
"the environment must be credited: {}",
env.stdout
);
let json = registry.mind(&["--json", "config", "show", "--max-metadata-size", "32MiB"]);
let doc: serde_json::Value = serde_json::from_str(&json.stdout)
.unwrap_or_else(|e| panic!("stdout must be one JSON document ({e}): {}", json.stdout));
assert_eq!(
doc["max_metadata_size_bytes"].as_i64(),
Some(32 * 1024 * 1024),
"a finite cap is emitted unchanged: {doc}"
);
}
#[test]
fn dsc110_every_zero_spelling_of_the_cap_means_unlimited() {
let registry = Sandbox::bare("dsc110-zero");
registry.write_sparse_and_commit("skills/huge/SKILL.md", METADATA_SIZE_LIMIT + 1);
let spec = registry.source_spec();
for value in ["0", "00", "0B", "0MiB", "0 mib", "0GB"] {
let r = registry.mind(&["review", &spec, "--max-metadata-size", value]);
assert!(
r.success,
"'{value}' must remove the ceiling: {} {}",
r.stdout, r.stderr
);
let combined = format!("{}{}", r.stdout, r.stderr);
assert!(
!combined.contains("size cap"),
"'{value}' must not report a cap at all: {combined}"
);
let env = registry.mind_env(
&["review", &spec],
&[("MIND_MAX_METADATA_SIZE", value)],
None,
);
assert!(
env.success,
"'{value}' from the environment must remove the ceiling too: {} {}",
env.stdout, env.stderr
);
let show = registry.mind(&["config", "show", "--max-metadata-size", value]);
assert!(
show.stdout.contains("max-metadata-size = unlimited"),
"'{value}' must report as unlimited, not as 0 bytes: {}",
show.stdout
);
}
let help = registry.mind(&["--help"]);
let help_text = format!("{}{}", help.stdout, help.stderr);
assert!(
help_text.contains("0MiB"),
"--help must name a zero-with-unit spelling among the accepted forms: {help_text}"
);
}
#[cfg(unix)]
#[test]
fn dsc111_a_non_unicode_env_cap_is_reported_rather_than_read_as_unset() {
use std::os::unix::ffi::OsStringExt;
let registry = Sandbox::bare("dsc111-nonunicode");
let bad = std::ffi::OsString::from_vec(vec![b'3', b'2', b'M', b'i', b'B', 0xff]);
let r = registry.mind_env_os(&["recall"], &[("MIND_MAX_METADATA_SIZE", bad)], None);
assert!(
!r.success,
"a set-but-undecodable cap must fail, not fall back to the default: {} {}",
r.stdout, r.stderr
);
let combined = format!("{}{}", r.stdout, r.stderr);
assert!(
combined.contains("MIND_MAX_METADATA_SIZE"),
"the error must name the origin: {combined}"
);
assert!(
combined.contains("UTF-8"),
"the error must say what is wrong with the value: {combined}"
);
let empty = registry.mind_env(&["recall"], &[("MIND_MAX_METADATA_SIZE", "")], None);
assert!(
empty.success,
"an empty value must still read as unset: {} {}",
empty.stdout, empty.stderr
);
}
#[cfg(unix)]
#[test]
fn dsc111_an_explicit_flag_outranks_a_non_unicode_env_cap() {
use std::os::unix::ffi::OsStringExt;
let registry = Sandbox::bare("dsc111-precedence");
let bad = std::ffi::OsString::from_vec(vec![0xff, 0xfe, b'!']);
let junk = registry.mind_env(
&["config", "show", "--max-metadata-size", "32MiB"],
&[("MIND_MAX_METADATA_SIZE", "banana")],
None,
);
assert!(
junk.success,
"an unparseable env value must be ignored when the flag sets the cap: {} {}",
junk.stdout, junk.stderr
);
assert!(
junk.stdout.contains("max-metadata-size = 32 MiB"),
"the flag's value must be the cap in force: {}",
junk.stdout
);
let r = registry.mind_env_os(
&["config", "show", "--max-metadata-size", "32MiB"],
&[("MIND_MAX_METADATA_SIZE", bad.clone())],
None,
);
assert!(
r.success,
"the flag must outrank an undecodable env value, not be pre-empted by it: {} {}",
r.stdout, r.stderr
);
assert!(
r.stdout.contains("max-metadata-size = 32 MiB"),
"the flag's value must be the cap in force: {} {}",
r.stdout,
r.stderr
);
let reported = registry.mind_env_os(
&["config", "show"],
&[("MIND_MAX_METADATA_SIZE", bad)],
None,
);
assert!(
!reported.success,
"with no flag the undecodable value is the origin and must be reported: {} {}",
reported.stdout, reported.stderr
);
}
#[cfg(unix)]
#[test]
fn dsc111_the_non_unicode_env_refusal_is_a_json_error_envelope_under_json() {
use std::os::unix::ffi::OsStringExt;
let registry = Sandbox::bare("dsc111-json");
let bad = std::ffi::OsString::from_vec(vec![b'8', b'M', b'i', b'B', 0x80]);
let r = registry.mind_env_os(
&["--json", "recall"],
&[("MIND_MAX_METADATA_SIZE", bad)],
None,
);
assert!(
!r.success,
"the run must still fail: {} {}",
r.stdout, r.stderr
);
let doc: serde_json::Value = serde_json::from_str(&r.stdout).unwrap_or_else(|e| {
panic!(
"stdout must be exactly one JSON document ({e}): {}",
r.stdout
)
});
assert_eq!(doc["schema"], 1, "the envelope must be schema 1: {doc}");
assert_eq!(
doc["error"]["kind"], "bad-metadata-size",
"the envelope must carry the machine-readable kind: {doc}"
);
assert!(
doc["error"]["message"]
.as_str()
.is_some_and(|m| m.contains("MIND_MAX_METADATA_SIZE") && m.contains("UTF-8")),
"the envelope message must name the origin and the fault: {doc}"
);
}
#[test]
fn dsc110_config_show_json_reports_a_zero_cap_as_the_documented_unlimited_pair() {
let registry = Sandbox::bare("dsc110-json");
let mut seen = Vec::new();
for value in ["0", "0MiB", "0GB", "unlimited", "none"] {
let r = registry.mind(&["--json", "config", "show", "--max-metadata-size", value]);
assert!(
r.success,
"'{value}' must be accepted: {} {}",
r.stdout, r.stderr
);
let doc: serde_json::Value = serde_json::from_str(&r.stdout)
.unwrap_or_else(|e| panic!("stdout must be one JSON document ({e}): {}", r.stdout));
assert_eq!(
doc["max_metadata_size"], "unlimited",
"'{value}' must render as the string `unlimited`: {doc}"
);
assert_eq!(
doc["max_metadata_size_bytes"].as_i64(),
Some(i64::MAX),
"'{value}' must carry the documented unlimited byte count: {doc}"
);
seen.push(doc["max_metadata_size_bytes"].clone());
}
assert!(
seen.windows(2).all(|w| w[0] == w[1]),
"every spelling of no ceiling must report the same pair: {seen:?}"
);
}
#[test]
fn dsc110_a_zero_with_a_huge_unit_is_unlimited_and_a_maximal_value_still_overflows() {
let registry = Sandbox::bare("dsc110-overflow");
let zero = registry.mind(&["config", "show", "--max-metadata-size", "0GiB"]);
assert!(
zero.success && zero.stdout.contains("max-metadata-size = unlimited"),
"a zero of any unit is unlimited: {} {}",
zero.stdout,
zero.stderr
);
let over = registry.mind(&[
"config",
"show",
"--max-metadata-size",
"18446744073709551615GiB",
]);
assert!(
!over.success,
"a value that overflows must be refused: {} {}",
over.stdout, over.stderr
);
assert!(
format!("{}{}", over.stdout, over.stderr).contains("overflow"),
"the refusal must say why: {} {}",
over.stdout,
over.stderr
);
}
#[test]
fn dsc110_a_value_that_only_begins_with_zero_is_not_unlimited() {
let registry = Sandbox::bare("dsc110-junk");
for value in ["0unlimited", "-0", "0.0MiB", "0x10", "0none", "00x0"] {
let arg = format!("--max-metadata-size={value}");
let r = registry.mind(&["config", "show", &arg]);
let combined = format!("{}{}", r.stdout, r.stderr);
assert!(
!r.success,
"'{value}' is not a size and must be refused: {combined}"
);
assert!(
combined.contains("--max-metadata-size"),
"'{value}': the refusal must name the origin: {combined}"
);
assert!(
!combined.contains("max-metadata-size ="),
"'{value}' must not report a cap in force at all: {combined}"
);
}
let padded = registry.mind(&["config", "show", "--max-metadata-size", "016MiB"]);
assert!(
padded.success && padded.stdout.contains("16 MiB"),
"a zero-padded count is the count it spells: {} {}",
padded.stdout,
padded.stderr
);
let spaced = registry.mind(&["config", "show", "--max-metadata-size", "0 0"]);
assert!(
spaced.success && spaced.stdout.contains("max-metadata-size = unlimited"),
"internal whitespace is not significant, so `0 0` is the zero `00`: {} {}",
spaced.stdout,
spaced.stderr
);
}
#[test]
fn learn_with_hostile_ns_token_fails_without_leaking_escape_bytes() {
let source = Sandbox::bare("ns-hostile");
source.write_and_commit(
"skills/review/SKILL.md",
"---\nname: review\ndescription: Review the diff\n---\n# review\n\
{{ns:\x1b]52;c;UEFZTE9BRA==\x07evil}}\n",
);
let meld = source.mind(&["meld", &source.source_spec(), "--link-only"]);
assert!(
meld.success,
"meld --link-only must register the source (the hostile token is only \
validated at install time): {} {}",
meld.stdout, meld.stderr
);
let learn = source.mind(&["learn", "skill:review"]);
assert!(
!learn.success,
"learning an item with an unresolvable hostile {{{{ns:}}}} token must fail"
);
let combined = format!("{}{}", learn.stdout, learn.stderr);
assert!(
!combined.contains('\x1b') && !combined.contains('\u{07}'),
"the BadReference error must not leak the raw ESC/BEL bytes of the \
OSC payload: {combined:?}"
);
assert!(
combined.contains("evil"),
"the error should still name enough of the referent to be \
actionable: {combined}"
);
}
#[test]
fn forget_with_hostile_link_outside_agent_homes_warns_without_leaking_escape() {
let sb = Sandbox::new("m9-link");
let r = sb.mind(&["meld", &sb.source_spec(), "--yes"]);
assert!(r.success, "meld --yes failed: {} {}", r.stdout, r.stderr);
assert!(
sb.claude_home.join("skills/review").exists(),
"the real review install must exist before the manifest hand-edit"
);
let manifest_path = sb.mind_home.join("manifest.json");
let raw = std::fs::read_to_string(&manifest_path).unwrap();
let mut doc: serde_json::Value = serde_json::from_str(&raw).unwrap();
let review = doc["items"]["skill:review"].clone();
assert!(!review.is_null(), "the review entry must exist: {doc}");
let mut hostile = review.clone();
hostile["name"] = serde_json::Value::String("hostile-link".to_string());
hostile["bare_name"] = serde_json::Value::String("hostile-link".to_string());
hostile["store"] = serde_json::Value::String("store/skill/hostile-link".to_string());
let hostile_link = "/does-not-exist-mind-test-root\x1b[31mRED\x1b[0m/../evil".to_string();
hostile["links"] = serde_json::Value::Array(vec![serde_json::Value::String(hostile_link)]);
doc["items"]["skill:hostile-link"] = hostile;
std::fs::write(&manifest_path, serde_json::to_vec_pretty(&doc).unwrap()).unwrap();
let forget = sb.mind(&["forget", "skill:hostile-link"]);
let combined = format!("{}{}", forget.stdout, forget.stderr);
assert!(
!combined.contains('\x1b'),
"the uninstall confinement warning must not leak a raw ESC byte: {combined:?}"
);
assert!(
combined.contains("outside all configured agent homes"),
"the warning text must still appear: {combined}"
);
assert!(
combined.contains("RED"),
"the warning must still show enough of the sanitized path to be \
actionable: {combined}"
);
assert!(sb.claude_home.join("skills/review").exists());
}
#[test]
fn forget_with_hostile_store_outside_root_warns_without_leaking_escape() {
let sb = Sandbox::new("m9-store");
let r = sb.mind(&["meld", &sb.source_spec(), "--yes"]);
assert!(r.success, "meld --yes failed: {} {}", r.stdout, r.stderr);
let manifest_path = sb.mind_home.join("manifest.json");
let raw = std::fs::read_to_string(&manifest_path).unwrap();
let mut doc: serde_json::Value = serde_json::from_str(&raw).unwrap();
let review = doc["items"]["skill:review"].clone();
assert!(!review.is_null(), "the review entry must exist: {doc}");
let mut hostile = review.clone();
hostile["name"] = serde_json::Value::String("hostile-store".to_string());
hostile["bare_name"] = serde_json::Value::String("hostile-store".to_string());
hostile["store"] =
serde_json::Value::String("../outside-mind-store-root\x1b[31mRED\x1b[0m".to_string());
hostile["links"] = serde_json::Value::Array(vec![]);
doc["items"]["skill:hostile-store"] = hostile;
std::fs::write(&manifest_path, serde_json::to_vec_pretty(&doc).unwrap()).unwrap();
let forget = sb.mind(&["forget", "skill:hostile-store"]);
let combined = format!("{}{}", forget.stdout, forget.stderr);
assert!(
!combined.contains('\x1b'),
"the uninstall confinement warning must not leak a raw ESC byte: {combined:?}"
);
assert!(
combined.contains("outside the mind store root"),
"the warning text must still appear: {combined}"
);
assert!(
combined.contains("RED"),
"the warning must still show enough of the sanitized path to be \
actionable: {combined}"
);
assert!(sb.claude_home.join("skills/review").exists());
}