use assert_cmd::prelude::*;
use std::process::Command;
#[test]
#[ignore = "requires ../cellos sibling on disk"]
fn cellos_dry_run_succeeds() {
let cellos_path = std::path::Path::new("../cellos");
if !cellos_path.exists() {
return;
}
let mut cmd = Command::cargo_bin("cordance").expect("bin");
cmd.arg("--target")
.arg("../cellos")
.arg("pack")
.arg("--output-mode")
.arg("dry-run");
cmd.assert().success();
}
#[test]
#[ignore = "requires ../cellos sibling on disk"]
fn cellos_dry_run_plans_harness_target() {
let cellos_path = std::path::Path::new("../cellos");
if !cellos_path.exists() {
return;
}
let mut cmd = Command::cargo_bin("cordance").expect("bin");
let output = cmd
.arg("--target")
.arg("../cellos")
.arg("pack")
.arg("--output-mode")
.arg("dry-run")
.output()
.expect("run cordance");
assert!(
output.status.success(),
"cordance failed: {}",
String::from_utf8_lossy(&output.stderr)
);
let stdout = String::from_utf8_lossy(&output.stdout);
assert!(
stdout.contains("pai-axiom-project-harness-target.json"),
"expected harness-target in dry-run output, got: {stdout}"
);
assert!(
stdout.contains("would write"),
"expected 'would write' in dry-run output, got: {stdout}"
);
}
#[test]
fn cellos_golden_fixture_has_correct_structure() {
let manifest = env!("CARGO_MANIFEST_DIR");
let fixture_path =
format!("{manifest}/../../fixtures/cellos-expected/pai-axiom-project-harness-target.json");
let json = std::fs::read_to_string(&fixture_path)
.unwrap_or_else(|e| panic!("failed to read cellos golden fixture: {e}"));
let value: serde_json::Value =
serde_json::from_str(&json).expect("golden fixture must be valid JSON");
assert_eq!(
value["schema"], "pai-axiom-project-harness-target.v1",
"schema must be pai-axiom-project-harness-target.v1"
);
assert_eq!(value["version"], 1, "version must be 1");
assert_eq!(
value["project"]["name"], "cellos",
"project.name must be cellos"
);
assert_eq!(
value["project"]["access_mode"], "read-only-advisory",
"project.access_mode must be read-only-advisory"
);
assert_eq!(
value["harness"]["claim_ceiling"], "candidate",
"harness.claim_ceiling must be candidate"
);
assert_eq!(
value["harness"]["classification"], "read-only-advisory",
"harness.classification must be read-only-advisory"
);
let allowed: Vec<&str> = value["harness"]["allowed_operations"]
.as_array()
.expect("allowed_operations must be array")
.iter()
.map(|v| v.as_str().expect("operation must be string"))
.collect();
assert!(
allowed.contains(&"inspect"),
"allowed_operations must include inspect"
);
assert!(
allowed.contains(&"validate-target"),
"allowed_operations must include validate-target"
);
assert!(
allowed.contains(&"emit-candidate-report"),
"allowed_operations must include emit-candidate-report"
);
let denied: Vec<&str> = value["harness"]["denied_operations"]
.as_array()
.expect("denied_operations must be array")
.iter()
.map(|v| v.as_str().expect("operation must be string"))
.collect();
assert!(
denied.contains(&"write-project-files"),
"denied_operations must include write-project-files"
);
assert!(
denied.contains(&"promote-project-doctrine"),
"denied_operations must include promote-project-doctrine"
);
assert!(
denied.contains(&"mutate-runtime-roots"),
"denied_operations must include mutate-runtime-roots"
);
assert!(
denied.contains(&"modify-release-gates"),
"denied_operations must include modify-release-gates"
);
assert!(
denied.contains(&"rewrite-adrs"),
"denied_operations must include rewrite-adrs"
);
let product_spec = value["authority_surfaces"]["product_spec"]
.as_array()
.expect("product_spec must be array");
assert!(
!product_spec.is_empty(),
"product_spec must not be empty for cellos"
);
let adrs = value["authority_surfaces"]["adrs"]
.as_array()
.expect("adrs must be array");
assert!(!adrs.is_empty(), "adrs must not be empty for cellos");
let tests_or_evals = value["authority_surfaces"]["tests_or_evals"]
.as_array()
.expect("tests_or_evals must be array");
assert!(
!tests_or_evals.is_empty(),
"tests_or_evals must not be empty for cellos"
);
}
#[test]
#[ignore = "requires ../cellos and ../pai-axiom siblings on disk"]
fn cellos_axiom_pin_is_stale_relative_to_latest() {
let latest_path = std::path::Path::new("../pai-axiom/PAI/Algorithm/LATEST");
if !latest_path.exists() {
return;
}
let current_latest = std::fs::read_to_string(latest_path)
.expect("read LATEST")
.trim()
.to_string();
let cellos_agents_path = std::path::Path::new("../cellos/AGENTS.md");
if !cellos_agents_path.exists() {
return;
}
let cellos_agents = std::fs::read_to_string(cellos_agents_path).expect("read cellos AGENTS.md");
if cellos_agents.contains("v3.1.0-axiom") && !cellos_agents.contains(¤t_latest) {
eprintln!("CONFIRMED: cellos AGENTS.md pins v3.1.0-axiom, but LATEST is {current_latest}");
eprintln!("Cordance would update it to {current_latest} on next pack.");
}
}