mod common;
use std::fs;
use predicates::prelude::*;
use common::{git, git_stdout, make_executable, truth_mirror};
#[test]
fn review_command_writes_ledger_with_mocked_reviewer_cli() {
let temp = tempfile::tempdir().unwrap();
let repo = temp.path().join("repo");
let bin = temp.path().join("bin");
fs::create_dir(&repo).unwrap();
fs::create_dir(&bin).unwrap();
git(&repo, &["init"]);
git(&repo, &["config", "user.email", "truth@example.invalid"]);
git(&repo, &["config", "user.name", "Truth Mirror Test"]);
fs::write(repo.join("file.txt"), "hello\n").unwrap();
git(&repo, &["add", "file.txt"]);
git(
&repo,
&[
"commit",
"-m",
"feat: add file",
"-m",
"CLAIM: add file | verified: cargo test | evidence: tests:review-e2e",
],
);
let sha = git_stdout(&repo, &["rev-parse", "HEAD"]);
let fake_codex = bin.join("codex");
fs::write(
&fake_codex,
r#"#!/usr/bin/env python3
import json
print(json.dumps({
"verdict": "PASS",
"summary": "The claim is substantiated.",
"findings": [],
"next_steps": [],
"memory_skill": {
"kind": "none",
"learning_source": "",
"reasoning": "This e2e fixture is not proposing a reusable skill."
}
}))
"#,
)
.unwrap();
make_executable(&fake_codex);
let path = format!(
"{}:{}",
bin.display(),
std::env::var("PATH").unwrap_or_default()
);
truth_mirror(&repo)
.env("PATH", path)
.args([
"--state-dir",
".truth-mirror",
"review",
"HEAD",
"--watched-agent",
"claude",
"--watched-model",
"model-a",
"--reviewer-harness",
"codex",
"--reviewer-model",
"model-b",
])
.assert()
.success()
.stdout(predicate::str::contains("truth-mirror review: run"));
let ledger = fs::read_to_string(repo.join(".truth-mirror/ledger.jsonl")).unwrap();
assert!(ledger.contains("\"verdict\":\"PASS\""));
truth_mirror(&repo)
.args(["--state-dir", ".truth-mirror", "review", "status"])
.assert()
.success()
.stdout(predicate::str::contains("completed"))
.stdout(predicate::str::contains(sha.as_str()));
truth_mirror(&repo)
.args(["--state-dir", ".truth-mirror", "review", "result"])
.assert()
.success()
.stdout(predicate::str::contains("status: completed"))
.stdout(predicate::str::contains("ledger_entries:"));
truth_mirror(&repo)
.args(["--state-dir", ".truth-mirror", "ledger", "stats"])
.assert()
.success()
.stdout(predicate::str::contains("pass=1"));
}
#[test]
fn review_head_records_entire_provenance_for_resolved_commit() {
let temp = tempfile::tempdir().unwrap();
let repo = temp.path().join("repo");
let bin = temp.path().join("bin");
fs::create_dir(&repo).unwrap();
fs::create_dir(&bin).unwrap();
git(&repo, &["init"]);
git(&repo, &["config", "user.email", "truth@example.invalid"]);
git(&repo, &["config", "user.name", "Truth Mirror Test"]);
fs::create_dir_all(repo.join(".entire/checkpoints")).unwrap();
fs::write(
repo.join(".entire/checkpoints/a1b2c3d4e5f6.json"),
r#"{"id":"a1b2c3d4e5f6"}"#,
)
.unwrap();
fs::write(repo.join("file.txt"), "hello\n").unwrap();
git(&repo, &["add", "file.txt"]);
git(
&repo,
&["add", "-f", ".entire/checkpoints/a1b2c3d4e5f6.json"],
);
git(
&repo,
&[
"commit",
"-m",
"feat: add file",
"-m",
"CLAIM: add file | verified: cargo test | evidence: tests:review-e2e",
"-m",
"Entire-Checkpoint: a1b2c3d4e5f6",
],
);
let sha = git_stdout(&repo, &["rev-parse", "HEAD"]);
git(
&repo,
&["update-ref", "refs/heads/entire/checkpoints/v1", "HEAD"],
);
let fake_codex = bin.join("codex");
fs::write(
&fake_codex,
r#"#!/usr/bin/env python3
import json
print(json.dumps({
"verdict": "PASS",
"summary": "The claim is substantiated.",
"findings": [],
"next_steps": [],
"memory_skill": {
"kind": "none",
"learning_source": "",
"reasoning": "Resolved commit provenance fixture is not a reusable memory-skill candidate."
}
}))
"#,
)
.unwrap();
make_executable(&fake_codex);
let path = format!(
"{}:{}",
bin.display(),
std::env::var("PATH").unwrap_or_default()
);
truth_mirror(&repo)
.env("PATH", path)
.args([
"--state-dir",
".truth-mirror",
"review",
"HEAD",
"--watched-agent",
"claude",
"--watched-model",
"model-a",
"--reviewer-harness",
"codex",
"--reviewer-model",
"model-b",
])
.assert()
.success();
let mut run_paths = fs::read_dir(repo.join(".truth-mirror/runs"))
.unwrap()
.map(|entry| entry.unwrap().path())
.collect::<Vec<_>>();
run_paths.sort();
assert_eq!(run_paths.len(), 1);
let run = run_paths.remove(0);
let run_json = fs::read_to_string(run).unwrap();
assert!(run_json.contains(&format!("\"commit_sha\": \"{sha}\"")));
assert!(run_json.contains("\"target\": \"commit:HEAD\""));
assert!(
run_json.contains("\"ref_name\": \"entire/checkpoints/v1\""),
"run_json={run_json}"
);
}
#[test]
fn review_strict_goal_loops_until_lie_threshold() {
let temp = tempfile::tempdir().unwrap();
let repo = temp.path().join("repo");
let bin = temp.path().join("bin");
fs::create_dir(&repo).unwrap();
fs::create_dir(&bin).unwrap();
git(&repo, &["init"]);
git(&repo, &["config", "user.email", "truth@example.invalid"]);
git(&repo, &["config", "user.name", "Truth Mirror Test"]);
fs::write(repo.join("file.txt"), "hello\n").unwrap();
git(&repo, &["add", "file.txt"]);
git(
&repo,
&[
"commit",
"-m",
"feat: add file",
"-m",
"CLAIM: add file | verified: cargo test | evidence: tests:strict-goal-e2e",
],
);
let fake_codex = bin.join("codex");
fs::write(
&fake_codex,
r#"#!/usr/bin/env python3
import json
print(json.dumps({
"verdict": "REJECT",
"summary": "The claim is not substantiated.",
"findings": [{
"severity": "high",
"title": "fabricated evidence",
"body": "The cited evidence does not prove the claim.",
"file": "file.txt",
"line_start": 1,
"line_end": 1,
"confidence": 95,
"recommendation": "Replace the claim with one supported by executable evidence."
}],
"next_steps": ["Run the real verification command."],
"memory_skill": {
"kind": "anti_pattern_skill",
"learning_source": "fabricated evidence",
"reasoning": "The rejection identifies a reusable false evidence pattern."
}
}))
"#,
)
.unwrap();
make_executable(&fake_codex);
let path = format!(
"{}:{}",
bin.display(),
std::env::var("PATH").unwrap_or_default()
);
truth_mirror(&repo)
.env("PATH", path)
.args([
"--state-dir",
".truth-mirror",
"review",
"HEAD",
"--watched-agent",
"claude",
"--watched-model",
"model-a",
"--reviewer-harness",
"codex",
"--reviewer-model",
"model-b",
"--strict-goal",
"--stop-after-lies",
"1",
"--max-passes",
"5",
])
.assert()
.success()
.stdout(predicate::str::contains("1 pass"))
.stdout(predicate::str::contains("1 lie"))
.stdout(predicate::str::contains("stopped: lies exposed"));
let ledger = fs::read_to_string(repo.join(".truth-mirror/ledger.jsonl")).unwrap();
assert!(ledger.contains("\"verdict\":\"REJECT\""));
}
#[test]
fn review_working_tree_scope_uses_claim_file_and_worktree_context() {
let temp = tempfile::tempdir().unwrap();
let repo = temp.path().join("repo");
let bin = temp.path().join("bin");
fs::create_dir(&repo).unwrap();
fs::create_dir(&bin).unwrap();
git(&repo, &["init"]);
git(&repo, &["config", "user.email", "truth@example.invalid"]);
git(&repo, &["config", "user.name", "Truth Mirror Test"]);
fs::write(repo.join("file.txt"), "hello\n").unwrap();
git(&repo, &["add", "file.txt"]);
git(
&repo,
&[
"commit",
"-m",
"feat: base",
"-m",
"CLAIM: base | verified: cargo test | evidence: tests:base",
],
);
fs::write(repo.join("file.txt"), "hello\nworld\n").unwrap();
fs::write(repo.join("new.txt"), "untracked\n").unwrap();
fs::create_dir(repo.join(".truth-mirror")).unwrap();
fs::write(
repo.join(".truth-mirror/claim.txt"),
"CLAIM: working tree change | verified: cargo test | evidence: tests:working-tree\n",
)
.unwrap();
let fake_codex = bin.join("codex");
fs::write(
&fake_codex,
r#"#!/usr/bin/env python3
import json
import sys
prompt = sys.argv[-1]
assert "WORKING TREE STATUS:" in prompt, prompt
assert "TRACKED DIFF AGAINST HEAD:" in prompt, prompt
assert "UNTRACKED FILES:" in prompt, prompt
print(json.dumps({
"verdict": "PASS",
"summary": "The working tree claim is substantiated.",
"findings": [],
"next_steps": [],
"memory_skill": {
"kind": "none",
"learning_source": "",
"reasoning": "Working-tree scope review is not a reusable memory-skill candidate."
}
}))
"#,
)
.unwrap();
make_executable(&fake_codex);
let path = format!(
"{}:{}",
bin.display(),
std::env::var("PATH").unwrap_or_default()
);
truth_mirror(&repo)
.env("PATH", path)
.args([
"--state-dir",
".truth-mirror",
"review",
"--scope",
"working-tree",
"--watched-agent",
"claude",
"--watched-model",
"model-a",
"--reviewer-harness",
"codex",
"--reviewer-model",
"model-b",
])
.assert()
.success();
let run = fs::read_dir(repo.join(".truth-mirror/runs"))
.unwrap()
.next()
.unwrap()
.unwrap()
.path();
let run_json = fs::read_to_string(run).unwrap();
assert!(run_json.contains("\"target\": \"working-tree\""));
}
#[test]
fn review_auto_scope_uses_working_tree_when_repo_is_dirty() {
let temp = tempfile::tempdir().unwrap();
let repo = temp.path().join("repo");
let bin = temp.path().join("bin");
fs::create_dir(&repo).unwrap();
fs::create_dir(&bin).unwrap();
git(&repo, &["init"]);
git(&repo, &["config", "user.email", "truth@example.invalid"]);
git(&repo, &["config", "user.name", "Truth Mirror Test"]);
fs::write(repo.join("file.txt"), "hello\n").unwrap();
git(&repo, &["add", "file.txt"]);
git(
&repo,
&[
"commit",
"-m",
"feat: base",
"-m",
"CLAIM: base | verified: cargo test | evidence: tests:base",
],
);
fs::write(repo.join("file.txt"), "hello\nauto\n").unwrap();
fs::create_dir(repo.join(".truth-mirror")).unwrap();
fs::write(
repo.join(".truth-mirror/claim.txt"),
"CLAIM: auto working tree change | verified: cargo test | evidence: tests:auto\n",
)
.unwrap();
let fake_codex = bin.join("codex");
fs::write(
&fake_codex,
r#"#!/usr/bin/env python3
import json
import sys
prompt = sys.argv[-1]
assert "WORKING TREE STATUS:" in prompt, prompt
assert "TRACKED DIFF AGAINST HEAD:" in prompt, prompt
print(json.dumps({
"verdict": "PASS",
"summary": "The auto-selected working tree claim is substantiated.",
"findings": [],
"next_steps": [],
"memory_skill": {
"kind": "none",
"learning_source": "",
"reasoning": "Auto-scope review fixture is not a reusable memory-skill candidate."
}
}))
"#,
)
.unwrap();
make_executable(&fake_codex);
let path = format!(
"{}:{}",
bin.display(),
std::env::var("PATH").unwrap_or_default()
);
truth_mirror(&repo)
.env("PATH", path)
.args([
"--state-dir",
".truth-mirror",
"review",
"--scope",
"auto",
"--watched-agent",
"claude",
"--watched-model",
"model-a",
"--reviewer-harness",
"codex",
"--reviewer-model",
"model-b",
])
.assert()
.success();
let run = fs::read_dir(repo.join(".truth-mirror/runs"))
.unwrap()
.next()
.unwrap()
.unwrap()
.path();
let run_json = fs::read_to_string(run).unwrap();
assert!(run_json.contains("\"target\": \"working-tree\""));
}
#[test]
fn review_branch_scope_uses_explicit_base_and_branch_context() {
let temp = tempfile::tempdir().unwrap();
let repo = temp.path().join("repo");
let bin = temp.path().join("bin");
fs::create_dir(&repo).unwrap();
fs::create_dir(&bin).unwrap();
git(&repo, &["init"]);
git(&repo, &["config", "user.email", "truth@example.invalid"]);
git(&repo, &["config", "user.name", "Truth Mirror Test"]);
fs::write(repo.join("file.txt"), "hello\n").unwrap();
git(&repo, &["add", "file.txt"]);
git(
&repo,
&[
"commit",
"-m",
"feat: base",
"-m",
"CLAIM: base | verified: cargo test | evidence: tests:base",
],
);
fs::write(repo.join("file.txt"), "hello\nbranch\n").unwrap();
git(&repo, &["add", "file.txt"]);
git(
&repo,
&[
"commit",
"-m",
"feat: branch",
"-m",
"CLAIM: branch change | verified: cargo test | evidence: tests:branch",
],
);
let fake_codex = bin.join("codex");
fs::write(
&fake_codex,
r#"#!/usr/bin/env python3
import json
import sys
prompt = sys.argv[-1]
assert "BRANCH BASE: HEAD~1" in prompt, prompt
assert "MERGE BASE:" in prompt, prompt
assert "COMMITS:" in prompt, prompt
print(json.dumps({
"verdict": "PASS",
"summary": "The branch claim is substantiated.",
"findings": [],
"next_steps": [],
"memory_skill": {
"kind": "none",
"learning_source": "",
"reasoning": "Branch-scope review fixture is not a reusable memory-skill candidate."
}
}))
"#,
)
.unwrap();
make_executable(&fake_codex);
let path = format!(
"{}:{}",
bin.display(),
std::env::var("PATH").unwrap_or_default()
);
truth_mirror(&repo)
.env("PATH", path)
.args([
"--state-dir",
".truth-mirror",
"review",
"--scope",
"branch",
"--base",
"HEAD~1",
"--watched-agent",
"claude",
"--watched-model",
"model-a",
"--reviewer-harness",
"codex",
"--reviewer-model",
"model-b",
])
.assert()
.success();
let run = fs::read_dir(repo.join(".truth-mirror/runs"))
.unwrap()
.next()
.unwrap()
.unwrap()
.path();
let run_json = fs::read_to_string(run).unwrap();
assert!(run_json.contains("\"target\": \"branch:HEAD~1\""));
}