use assert_cmd::Command;
use predicates::prelude::*;
use truth_mirror::ledger::{LedgerEntry, LedgerStore, ReviewerConfig, Verdict};
fn seed_rejection(state_dir: &std::path::Path, sha: &str) {
let store = LedgerStore::new(state_dir);
store
.append_entry(&LedgerEntry::new_at(
sha,
Verdict::Reject,
"CLAIM: rejected | verified: cargo test | evidence: tests:cargo-test",
vec!["tests:cargo-test".to_owned()],
ReviewerConfig::new("claude", "claude-opus-4-1", false),
vec!["unsupported claim".to_owned()],
100,
))
.unwrap();
}
#[test]
fn ledger_list_shows_unresolved_rejection() {
let temp = tempfile::tempdir().unwrap();
seed_rejection(temp.path(), "abc123");
Command::cargo_bin("truth-mirror")
.unwrap()
.args([
"--state-dir",
temp.path().to_str().unwrap(),
"ledger",
"list",
])
.assert()
.success()
.stdout(predicate::str::contains("abc123"))
.stdout(predicate::str::contains("REJECT"));
}
#[test]
fn ledger_show_prints_entry_details() {
let temp = tempfile::tempdir().unwrap();
seed_rejection(temp.path(), "abc123");
Command::cargo_bin("truth-mirror")
.unwrap()
.args([
"--state-dir",
temp.path().to_str().unwrap(),
"ledger",
"show",
"abc123",
])
.assert()
.success()
.stdout(predicate::str::contains("unsupported claim"));
}
#[test]
fn reinject_claude_is_quiet_when_grok_env_and_skill_present() {
let temp = tempfile::tempdir().unwrap();
seed_rejection(temp.path(), "abc123");
let skill = temp.path().join(".grok/skills/truth-mirror/SKILL.md");
std::fs::create_dir_all(skill.parent().unwrap()).unwrap();
std::fs::write(
&skill,
format!(
"{}\nrun truth-mirror reinject --agent grok\n",
truth_mirror::surface::GROK_SKILL_MANAGED_MARKER
),
)
.unwrap();
Command::cargo_bin("truth-mirror")
.unwrap()
.current_dir(temp.path())
.env("GROK_SESSION_ID", "sess-test")
.env("GROK_HOOK_EVENT", "user_prompt_submit")
.args([
"--state-dir",
temp.path().to_str().unwrap(),
"reinject",
"--agent",
"claude",
])
.assert()
.success()
.stdout(predicate::str::is_empty());
}
#[test]
fn reinject_claude_warns_under_grok_without_skill() {
let temp = tempfile::tempdir().unwrap();
seed_rejection(temp.path(), "abc123");
Command::cargo_bin("truth-mirror")
.unwrap()
.current_dir(temp.path())
.env("GROK_SESSION_ID", "sess-test")
.env_remove("GROK_HOOK_EVENT")
.args([
"--state-dir",
temp.path().to_str().unwrap(),
"reinject",
"--agent",
"claude",
])
.assert()
.success()
.stderr(predicate::str::contains("without"))
.stdout(predicate::str::contains("Claude"))
.stdout(predicate::str::contains("abc123"));
}
#[test]
fn reinject_grok_still_prints_under_grok_env() {
let temp = tempfile::tempdir().unwrap();
seed_rejection(temp.path(), "abc123");
Command::cargo_bin("truth-mirror")
.unwrap()
.env("GROK_SESSION_ID", "sess-test")
.env("GROK_HOOK_EVENT", "user_prompt_submit")
.args([
"--state-dir",
temp.path().to_str().unwrap(),
"reinject",
"--agent",
"grok",
])
.assert()
.success()
.stdout(predicate::str::contains("Grok"))
.stdout(predicate::str::contains("abc123"));
}
#[test]
fn reinject_claude_still_prints_without_grok_env() {
let temp = tempfile::tempdir().unwrap();
seed_rejection(temp.path(), "abc123");
Command::cargo_bin("truth-mirror")
.unwrap()
.env_remove("GROK_SESSION_ID")
.env_remove("GROK_HOOK_EVENT")
.args([
"--state-dir",
temp.path().to_str().unwrap(),
"reinject",
"--agent",
"claude",
])
.assert()
.success()
.stdout(predicate::str::contains("Claude"))
.stdout(predicate::str::contains("abc123"));
}