truth-mirror 0.4.0

Truthfulness gate and adversarial reviewer harness for AI coding agents.
Documentation
use assert_cmd::Command;
use predicates::prelude::*;

#[test]
fn skills_echo_prints_skill_document() {
    Command::cargo_bin("truth-mirror")
        .unwrap()
        .args(["skills", "echo"])
        .assert()
        .success()
        .stdout(predicate::str::contains("CLAIM:"))
        .stdout(predicate::str::contains("Ground truth files"));
}

#[test]
fn skills_install_writes_skill_into_default_dir() {
    let temp = tempfile::tempdir().unwrap();

    Command::cargo_bin("truth-mirror")
        .unwrap()
        .current_dir(temp.path())
        .args(["skills", "install"])
        .assert()
        .success()
        .stdout(predicate::str::contains("truth-mirror/SKILL.md"));

    let written =
        std::fs::read_to_string(temp.path().join(".agents/skills/truth-mirror/SKILL.md")).unwrap();
    assert!(written.contains("CLAIM:"));
    assert!(written.contains("Ground truth files"));
}

#[test]
fn skills_install_refuses_overwrite_without_force() {
    let temp = tempfile::tempdir().unwrap();

    Command::cargo_bin("truth-mirror")
        .unwrap()
        .current_dir(temp.path())
        .args(["skills", "install"])
        .assert()
        .success();

    let target = temp.path().join(".agents/skills/truth-mirror/SKILL.md");
    std::fs::write(&target, "HAND-CRAFTED SENTINEL").unwrap();

    Command::cargo_bin("truth-mirror")
        .unwrap()
        .current_dir(temp.path())
        .args(["skills", "install"])
        .assert()
        .failure()
        .stderr(predicate::str::contains("refusing to overwrite"));

    let after = std::fs::read_to_string(&target).unwrap();
    assert_eq!(after, "HAND-CRAFTED SENTINEL");
}

#[test]
fn skills_install_force_overwrites_existing() {
    let temp = tempfile::tempdir().unwrap();
    let target = temp.path().join(".agents/skills/truth-mirror/SKILL.md");

    Command::cargo_bin("truth-mirror")
        .unwrap()
        .current_dir(temp.path())
        .args(["skills", "install"])
        .assert()
        .success();

    std::fs::write(&target, "HAND-CRAFTED SENTINEL").unwrap();

    Command::cargo_bin("truth-mirror")
        .unwrap()
        .current_dir(temp.path())
        .args(["skills", "install", "--force"])
        .assert()
        .success();

    let after = std::fs::read_to_string(&target).unwrap();
    assert!(after.contains("CLAIM:"));
    assert!(!after.contains("HAND-CRAFTED SENTINEL"));
}

#[test]
fn skills_install_respects_custom_dir() {
    let temp = tempfile::tempdir().unwrap();
    let custom = temp.path().join("custom-skills");

    Command::cargo_bin("truth-mirror")
        .unwrap()
        .args(["skills", "install", "--dir", custom.to_str().unwrap()])
        .assert()
        .success()
        .stdout(predicate::str::contains(
            "custom-skills/truth-mirror/SKILL.md",
        ));

    let written = std::fs::read_to_string(custom.join("truth-mirror/SKILL.md")).unwrap();
    assert!(written.contains("CLAIM:"));
}