#[path = "support/run.rs"]
mod owned_run;
use std::{fs, path::Path, process::Command};
use artifactize_core::{
cache, human,
project::{VerifyOptions, selection::Selection},
remote::Record,
store::OwnedReceipts,
};
use rusqlite::Connection;
use serde_json::{Value, json};
use support::os::{cat_program, true_program};
use tokio_util::sync::CancellationToken;
#[path = "../../artifactize-core/tests/support/mod.rs"]
mod support;
use support::runs::RecordOutput;
fn cli(state: &Path, args: &[&str]) -> Value {
let output = Command::new(support::os::cli())
.arg("--state-dir")
.arg(state)
.args(args)
.arg("--json")
.record_output()
.unwrap();
assert!(
output.status.success(),
"{}",
String::from_utf8_lossy(&output.stderr)
);
serde_json::from_slice(&output.stdout).unwrap()
}
fn write_repo(repo: &Path, profile: Value) {
fs::create_dir_all(repo).unwrap();
fs::write(repo.join("fingerprint"), "remote-v1\n").unwrap();
support::os::write_python_script(
&repo.join("check.py"),
"sys.stdout.buffer.write(b'stdout-marker\\n')\nsys.stderr.buffer.write(b'stderr-marker\\n')\n",
);
support::declaration::write(
repo.join("index.artf"),
json!({
"name":"app",
"fingerprint":{"script":{"command":cat_program(),"args":["fingerprint"]}},
"evals":[
{
"id":"check",
"title":"Check",
"profile":profile,
"payload":{"instruction":"Review."},
"pass_schema":{
"type":"object",
"properties":{"approved":{"const":true}},
"required":["approved"],
"additionalProperties":false,
},
},
],
})
.to_string(),
)
.unwrap();
}
async fn verify(repo: &Path, state: &Path) -> artifactize_core::store::RunView {
support::runs::record(
repo,
Some(state),
&Selection::All,
&VerifyOptions {
..Default::default()
},
CancellationToken::new(),
)
.await
.unwrap()
}
#[tokio::test]
async fn runtime_summary_omits_local_audit_and_its_mirror_is_reusable() {
let root = owned_run::Root::from(support::os::tempdir());
let repo = root.path().join("repo");
write_repo(
&repo,
json!({"kind":"runtime","command":support::os::python_program(),"args":["-I","check.py"]}),
);
let producer_state = root.path().join("producer");
root.track(&producer_state, &repo);
let produced = verify(&repo, &producer_state).await;
assert_eq!(produced.run.status().as_str(), "GREEN");
let key = produced.requests[0].key.clone().unwrap();
let execution = cache::show(&producer_state, &key, false)
.await
.unwrap()
.pop()
.unwrap();
assert_eq!(execution.fingerprint.as_deref(), Some("remote-v1"));
assert_eq!(
execution.fingerprints,
[("app".parse().unwrap(), "remote-v1".parse().unwrap())].into()
);
let producer = execution.producer.clone().unwrap();
assert_eq!(producer.version, env!("CARGO_PKG_VERSION"));
assert!(producer.name.contains('@'));
assert_eq!(
execution.result().unwrap().to_json()["stdout"],
"stdout-marker\n"
);
let summary = Record::new(&execution, false).unwrap();
let text = serde_json::to_string(&summary).unwrap();
for leaked in [
"argv",
"stdout",
"stderr",
"toolCalls",
"repoPath",
"marker",
] {
assert!(!text.contains(leaked), "{leaked} in {text}");
}
assert!(
!text.contains(&support::os::path_text(root.path())),
"{text}"
);
let summary_json = summary.result.to_json();
let mut keys: Vec<_> = summary_json.as_object().unwrap().keys().collect();
keys.sort();
assert_eq!(keys, ["durationMs", "exitCode", "truncated", "verdict"]);
let full = Record::new(&execution, true).unwrap();
let mut earlier = serde_json::to_value(&full).unwrap();
earlier["execution"]["toolCalls"] = json!([{"name":"read","isError":false}]);
earlier["execution"]["options"]["resultCheckTimeoutMs"] = json!(5000);
let earlier: Record = serde_json::from_value(earlier).unwrap();
assert!(
!serde_json::to_string(&earlier)
.unwrap()
.contains("toolCalls")
);
assert_eq!(
full.execution.unwrap().result().unwrap().to_json()["stderr"],
"stderr-marker\n"
);
let mut stored = summary;
stored.publisher = Some("alice-laptop".parse().unwrap());
stored.published_at = Some("2026-10-04T00:00:00Z".parse().unwrap());
let consumer_state = root.path().join("consumer");
root.track(&consumer_state, &repo);
let receipts = OwnedReceipts::open(&consumer_state, &repo).await.unwrap();
let mirror = stored.mirror("https://reviews.example/").unwrap();
let mirrored = receipts.mirror_execution(&mirror).await.unwrap().unwrap();
assert_eq!(mirrored.id.as_str(), format!("remote-{}", execution.id));
assert!(receipts.mirror_execution(&mirror).await.unwrap().is_none());
assert_eq!(
cli(&consumer_state, &["cache", "list", "--history"])
.as_array()
.unwrap()
.len(),
1
);
assert!(Record::new(&mirrored, false).is_err());
let shown = cli(&consumer_state, &["cache", "show", &key]);
assert_eq!(
shown["origin"],
json!({
"store":"https://reviews.example/",
"publisher":"alice-laptop",
"publishedAt":"2026-10-04T00:00:00.000000000Z",
})
);
assert_eq!(shown["producer"], json!(producer));
assert_eq!(shown["status"], "GREEN");
assert!(shown["result"].get("stdout").is_none());
assert_eq!(
cli(&consumer_state, &["cache", "list"])[0]["origin"],
"https://reviews.example/"
);
let reused = verify(&repo, &consumer_state).await;
assert_eq!(reused.run.status().as_str(), "GREEN");
assert_eq!(reused.run.executions_started, 0);
assert_eq!(reused.requests[0].execution_id.as_ref(), Some(&mirrored.id));
Connection::open(producer_state.join("state.sqlite"))
.unwrap()
.execute(
"UPDATE executions SET data=json_remove(data,'$.producer')",
[],
)
.unwrap();
assert!(
cli(&producer_state, &["cache", "show", &key])
.get("producer")
.is_none()
);
}
#[tokio::test]
async fn maximum_wire_execution_ids_mirror_and_reuse_without_renaming() {
let root = owned_run::Root::from(support::os::tempdir());
let repo = root.path().join("repo");
write_repo(
&repo,
json!({"kind":"runtime","command":true_program(),"args":[]}),
);
let producer_state = root.path().join("producer");
root.track(&producer_state, &repo);
let produced = verify(&repo, &producer_state).await;
let key = produced.requests[0].key.as_ref().unwrap();
let original = cache::show(&producer_state, key, false)
.await
.unwrap()
.pop()
.unwrap();
for bytes in [193, 194, 200] {
for full in [false, true] {
let mut source = original.clone();
source.id = "x".repeat(bytes).parse().unwrap();
let mut wire = Record::new(&source, full).unwrap();
wire.publisher = Some("alice-laptop".parse().unwrap());
wire.published_at = Some("2026-10-04T00:00:02Z".parse().unwrap());
let wire: Record = serde_json::from_value(serde_json::to_value(wire).unwrap()).unwrap();
wire.validate().unwrap();
let mirror = wire.mirror("https://reviews.example/").unwrap();
assert_eq!(mirror.id.as_str(), format!("remote-{}", source.id));
assert_eq!(mirror.id.len(), bytes + "remote-".len());
let state = root.path().join(format!("consumer-{bytes}-{full}"));
root.track(&state, &repo);
let receipts = OwnedReceipts::open(&state, &repo).await.unwrap();
receipts.mirror_execution(&mirror).await.unwrap().unwrap();
assert!(receipts.mirror_execution(&mirror).await.unwrap().is_none());
let saved = cache::show(&state, key, false)
.await
.unwrap()
.pop()
.unwrap();
assert_eq!(saved.id, mirror.id);
assert_eq!(
cache::list(&state, false).await.unwrap()[0].execution_id,
mirror.id
);
let reused = verify(&repo, &state).await;
assert_eq!(reused.run.status().as_str(), "GREEN");
assert_eq!(reused.run.executions_started, 0);
assert_eq!(reused.requests[0].execution_id.as_ref(), Some(&mirror.id));
}
}
let mut too_long = Record::new(&original, false).unwrap();
too_long.execution_id = format!("remote-{}", "x".repeat(194)).parse().unwrap();
assert!(too_long.validate().is_err());
}
#[tokio::test]
async fn legacy_207_byte_mirrors_remain_readable_in_json_sql_and_cache() {
let text = include_str!("../../artifactize-core/tests/fixtures/legacy_remote_execution.json");
let execution: artifactize_core::store::Execution = serde_json::from_str(text).unwrap();
assert_eq!(execution.id.len(), 207);
let state = support::os::tempdir();
let repo = support::os::tempdir();
OwnedReceipts::open(state.path(), repo.path())
.await
.unwrap();
let db = Connection::open(state.path().join("state.sqlite")).unwrap();
db.execute(
"INSERT INTO executions(id,key,eval_def_hash,status,owner_pid,owner_start_time,completed_at,bytes,last_used,data) VALUES(?1,?2,?3,'GREEN',0,0,?4,?5,?4,?6)",
rusqlite::params![
execution.id,
execution.key,
execution.eval_def_hash,
execution.completed_at(),
text.len() as i64,
text
],
)
.unwrap();
assert_eq!(
cache::list(state.path(), false).await.unwrap()[0].execution_id,
execution.id
);
assert_eq!(
cache::show(state.path(), execution.key.as_ref().unwrap(), false)
.await
.unwrap()[0]
.id,
execution.id
);
}
#[tokio::test]
async fn human_summary_keeps_owner_fields_and_the_reviewer() {
let root = owned_run::Root::from(support::os::tempdir());
let repo = root.path().join("repo");
write_repo(&repo, json!({"kind":"human"}));
let state = root.path().join("state");
root.track(&state, &repo);
let waiting = verify(&repo, &state).await;
let request = &waiting.requests[0];
assert_eq!(request.status().as_str(), "WAITING_HUMAN");
let receipts = OwnedReceipts::open(&state, &repo).await.unwrap();
human::claim(&receipts, &request.id, &"alice".parse().unwrap())
.await
.unwrap();
human::submit(
&receipts,
&request.id,
&"alice".parse().unwrap(),
&json!({"verdict":"GREEN","approved":true}),
CancellationToken::new(),
)
.await
.unwrap();
let execution = cache::show(&state, request.key.as_deref().unwrap(), false)
.await
.unwrap()
.pop()
.unwrap();
assert_eq!(execution.reviewer.as_deref(), Some("alice"));
let summary = Record::new(&execution, false).unwrap();
assert_eq!(summary.reviewer.as_deref(), Some("alice"));
assert_eq!(
summary.result.to_json(),
json!({"verdict":"GREEN","approved":true})
);
}
#[tokio::test]
async fn an_agent_result_is_reused_across_models_and_shows_its_profile() {
use artifactize_core::{
config::{Profile, read_workspace_config},
store::{Execution, ExecutionOptions, Producer, Provenance},
};
let root = owned_run::Root::from(support::os::tempdir());
let repo = root.path().join("repo");
let declared = json!({
"kind":"agent",
"backend":"openai",
"model":"model-a",
"reasoning":"high",
"timeout_ms":60000,
});
let fast = json!({
"kind":"agent",
"backend":"anthropic",
"model":"model-b",
"reasoning":"low",
"max_tokens":500,
});
write_repo(&repo, declared.clone());
let path = repo.join("index.artf");
let mut declaration: Value = support::declaration::read(fs::read(&path).unwrap()).unwrap();
declaration["evals"][0]["profile_variants"] = json!({ "fast": fast });
support::declaration::write(&path, declaration.to_string()).unwrap();
let config = read_workspace_config(&repo).unwrap();
let state = root.path().join("state");
root.track(&state, &repo);
let fingerprints = cache::prepare(
&config,
[&config.artifacts["app"].name],
&state,
&cache::Parallelism::new(2),
CancellationToken::new(),
)
.await
.unwrap();
let key = cache::eval_keys(&config, &fingerprints)[&config.evals[0].id].clone();
let variant: Profile = serde_json::from_value(fast.clone()).unwrap();
let completed: artifactize_core::types::Timestamp = "2026-10-04T00:00:01Z".parse().unwrap();
let produced = Execution {
id: "execution-run-elsewhere-1".parse().unwrap(),
key: Some(key.value.clone()),
fingerprint: Some("remote-v1".parse().unwrap()),
fingerprints: key.fingerprints.clone(),
artifact_kinds: key.artifact_kinds.clone(),
eval_def_hash: key.eval_def_hash.clone(),
owner: Some(artifactize_core::process::ChildIdentity {
pid: artifactize_core::process::ProcessId::new(1),
start_time: 1,
}),
state: artifactize_core::store::ExecutionState::Completed {
result: json!({"verdict":"GREEN","approved":true})
.try_into()
.unwrap(),
at: completed,
},
profile: artifactize_core::config::StoredProfile::from(&variant),
options: ExecutionOptions::new(&variant, Some(&"fast".parse().unwrap())),
usage: Some(
serde_json::from_value(json!([{"turn":1,"attempt":1,"usage":{"inputTokens":10}}]))
.unwrap(),
),
provenance: Provenance {
repo_path: root.path().join("elsewhere"),
run_id: "run-elsewhere".parse().unwrap(),
request_id: "run-elsewhere-1".parse().unwrap(),
eval_id: "app/check".parse().unwrap(),
eval_def_hash: key.eval_def_hash.clone(),
completed_at: Some(completed),
execution_paths: Default::default(),
},
started_at: "2026-10-04T00:00:00Z".parse().unwrap(),
producer: Some(Producer {
name: "bob@laptop".parse().unwrap(),
version: "0.5.0".into(),
session: None,
}),
reviewer: None,
origin: None,
manifest: None,
};
let mut record = Record::new(&produced, false).unwrap();
assert_eq!(record.options.model.as_deref(), Some("model-b"));
record.publisher = Some("bob-laptop".parse().unwrap());
record.published_at = Some("2026-10-04T00:00:02Z".parse().unwrap());
let receipts = OwnedReceipts::open(&state, &repo).await.unwrap();
receipts
.mirror_execution(&record.mirror("https://reviews.example/").unwrap())
.await
.unwrap();
let reused = verify(&repo, &state).await;
assert_eq!(reused.run.status().as_str(), "GREEN");
assert_eq!(reused.run.executions_started, 0);
let request = &reused.requests[0];
assert_eq!(
serde_json::to_value(&request.profile).unwrap(),
json!({
"kind":"agent", "backend":"anthropic", "model":"model-b",
"reasoning":"low", "timeoutMs":null, "maxToolCalls":null, "maxTokens":500,
})
);
assert_eq!(
serde_json::to_value(&request.requested_profile).unwrap()["model"],
declared["model"]
);
assert_eq!(
serde_json::to_value(&request.requested_profile).unwrap()["backend"],
declared["backend"]
);
assert_eq!(request.options.variant.as_deref(), Some("fast"));
assert_eq!(
request.options.backend,
Some(artifactize_core::config::Backend::Anthropic)
);
assert_eq!(request.options.max_tokens, Some(500));
let shown = cli(&state, &["cache", "show", &key.value]);
assert_eq!(
shown["options"],
json!({
"backend":"anthropic",
"model":"model-b",
"reasoning":"low",
"maxTokens":500,
"variant":"fast",
})
);
declaration["evals"][0]["profile"] = json!({
"kind":"agent",
"backend":"openai",
"model":"model-c",
"max_tool_calls":3,
"timeout_ms":1000,
});
support::declaration::write(&path, declaration.to_string()).unwrap();
let again = verify(&repo, &state).await;
assert_eq!(again.run.executions_started, 0);
assert_eq!(again.requests[0].key.as_deref(), Some(key.value.as_str()));
assert_eq!(again.requests[0].execution_id, request.execution_id);
}