use std::fs;
use std::path::PathBuf;
use serde_json::{Value, json};
const EXPECTED_PRIMITIVES: &[(&str, &str)] = &[
("finding", "carina.finding.v0.1"),
("evidence", "carina.evidence.v0.1"),
("artifact", "carina.artifact.v0.1"),
("proposal", "carina.proposal.v0.1"),
("diff", "carina.diff.v0.1"),
("event", "carina.event.v0.1"),
("attestation", "carina.attestation.v0.1"),
("question", "carina.question.v0.1"),
("protocol", "carina.protocol.v0.1"),
("experiment", "carina.experiment.v0.1"),
("mechanism", "carina.mechanism.v0.1"),
("lineage", "carina.lineage.v0.1"),
("confidence", "carina.confidence.v0.1"),
];
fn primitives_example_path() -> PathBuf {
let manifest_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
manifest_dir
.parent()
.and_then(|p| p.parent())
.expect("crates/vela-protocol parent")
.join("examples/carina-kernel/primitives.v0.1.json")
}
#[test]
fn carina_primitives_example_exists() {
let path = primitives_example_path();
assert!(
path.is_file(),
"Carina primitives example missing at {}",
path.display()
);
}
#[test]
fn carina_primitives_example_parses() {
let path = primitives_example_path();
let raw = fs::read_to_string(&path).expect("read primitives example");
let value: Value = serde_json::from_str(&raw).expect("parse primitives example");
assert_eq!(
value.get("schema").and_then(Value::as_str),
Some("carina.examples.v0.1"),
"wrapper schema must be carina.examples.v0.1"
);
let primitives = value
.get("primitives")
.and_then(Value::as_object)
.expect("primitives object");
assert!(
!primitives.is_empty(),
"primitives object must be non-empty"
);
}
#[test]
fn carina_primitives_example_covers_every_documented_primitive() {
let path = primitives_example_path();
let raw = fs::read_to_string(&path).expect("read primitives example");
let value: Value = serde_json::from_str(&raw).expect("parse primitives example");
let primitives = value
.get("primitives")
.and_then(Value::as_object)
.expect("primitives object");
for (key, schema) in EXPECTED_PRIMITIVES {
let entry = primitives
.get(*key)
.unwrap_or_else(|| panic!("Carina primitive '{key}' missing from {}", path.display()));
let actual_schema = entry
.get("schema")
.and_then(Value::as_str)
.unwrap_or_else(|| panic!("primitive '{key}' is missing 'schema' field"));
assert_eq!(
actual_schema, *schema,
"primitive '{key}' must declare schema '{schema}'"
);
let object = entry
.as_object()
.unwrap_or_else(|| panic!("primitive '{key}' must be a JSON object"));
let non_schema_fields = object.keys().filter(|k| k.as_str() != "schema").count();
assert!(
non_schema_fields >= 2,
"primitive '{key}' has too few fields ({non_schema_fields}); expected at least 2 non-schema fields"
);
}
}
#[test]
fn carina_primitives_example_artifact_packet_validates() {
let path = primitives_example_path();
let raw = fs::read_to_string(&path).expect("read primitives example");
let value: Value = serde_json::from_str(&raw).expect("parse primitives example");
let artifact = value
.pointer("/primitives/artifact")
.expect("artifact primitive");
let id = artifact.get("id").and_then(Value::as_str);
assert!(id.is_some_and(|s| !s.is_empty()), "artifact id required");
let locator = artifact.get("locator").and_then(Value::as_str);
assert!(
locator.is_some_and(|s| !s.is_empty()),
"artifact locator required for the artifact_packet boundary"
);
}
#[test]
fn carina_primitives_example_finding_has_assertion_and_confidence() {
let path = primitives_example_path();
let raw = fs::read_to_string(&path).expect("read primitives example");
let value: Value = serde_json::from_str(&raw).expect("parse primitives example");
let finding = value
.pointer("/primitives/finding")
.expect("finding primitive");
assert!(
finding
.pointer("/assertion/text")
.and_then(Value::as_str)
.is_some_and(|s| !s.is_empty()),
"finding.assertion.text required"
);
let confidence = finding
.pointer("/confidence")
.and_then(Value::as_object)
.expect("finding.confidence object");
let score = confidence.get("score").and_then(Value::as_f64);
assert!(
score.is_some_and(|v| (0.0..=1.0).contains(&v)),
"confidence.score must be in [0.0, 1.0]"
);
}
#[test]
fn carina_primitives_example_event_has_target_and_actor() {
let path = primitives_example_path();
let raw = fs::read_to_string(&path).expect("read primitives example");
let value: Value = serde_json::from_str(&raw).expect("parse primitives example");
let event = value.pointer("/primitives/event").expect("event primitive");
assert!(
event
.pointer("/target/type")
.and_then(Value::as_str)
.is_some_and(|s| !s.is_empty()),
"event.target.type required"
);
assert!(
event
.pointer("/target/id")
.and_then(Value::as_str)
.is_some_and(|s| !s.is_empty()),
"event.target.id required"
);
assert!(
event
.pointer("/actor/id")
.and_then(Value::as_str)
.is_some_and(|s| !s.is_empty()),
"event.actor.id required"
);
}
fn load_primitives() -> Value {
let path = primitives_example_path();
let raw = fs::read_to_string(&path).expect("read primitives example");
serde_json::from_str(&raw).expect("parse primitives example")
}
fn primitive<'a>(value: &'a Value, key: &str) -> &'a Value {
value
.pointer(&format!("/primitives/{key}"))
.unwrap_or_else(|| panic!("Carina primitive '{key}' missing"))
}
fn assert_str_field(entry: &Value, key: &str, primitive_name: &str) {
let present = entry
.get(key)
.and_then(Value::as_str)
.is_some_and(|s| !s.is_empty());
assert!(
present,
"primitive '{primitive_name}' is missing required string field '{key}'"
);
}
fn assert_array_field(entry: &Value, key: &str, primitive_name: &str) {
let present = entry.get(key).and_then(Value::as_array).is_some();
assert!(
present,
"primitive '{primitive_name}' is missing required array field '{key}'"
);
}
fn assert_object_field(entry: &Value, key: &str, primitive_name: &str) {
let present = entry.get(key).and_then(Value::as_object).is_some();
assert!(
present,
"primitive '{primitive_name}' is missing required object field '{key}'"
);
}
#[test]
fn carina_primitive_finding_has_required_fields() {
let value = load_primitives();
let finding = primitive(&value, "finding");
assert_str_field(finding, "id", "finding");
assert_object_field(finding, "assertion", "finding");
assert_str_field(
finding.pointer("/assertion").unwrap(),
"text",
"finding.assertion",
);
assert_str_field(
finding.pointer("/assertion").unwrap(),
"type",
"finding.assertion",
);
assert_object_field(finding, "conditions", "finding");
assert_array_field(finding, "evidence_ids", "finding");
assert_object_field(finding, "confidence", "finding");
let confidence = finding.pointer("/confidence").unwrap();
assert_str_field(confidence, "method", "finding.confidence");
assert_str_field(confidence, "scope", "finding.confidence");
assert!(
confidence
.get("score")
.and_then(Value::as_f64)
.is_some_and(|v| (0.0..=1.0).contains(&v)),
"finding.confidence.score must be in [0.0, 1.0]"
);
assert_object_field(finding, "lineage", "finding");
assert_str_field(finding, "status", "finding");
}
#[test]
fn carina_primitive_evidence_has_required_fields() {
let value = load_primitives();
let evidence = primitive(&value, "evidence");
assert_str_field(evidence, "id", "evidence");
assert_str_field(evidence, "source_id", "evidence");
assert_str_field(evidence, "artifact_id", "evidence");
assert_str_field(evidence, "locator", "evidence");
assert_str_field(evidence, "span", "evidence");
assert_array_field(evidence, "supports", "evidence");
assert_array_field(evidence, "limitations", "evidence");
}
#[test]
fn carina_primitive_artifact_has_required_fields() {
let value = load_primitives();
let artifact = primitive(&value, "artifact");
assert_str_field(artifact, "id", "artifact");
assert_str_field(artifact, "kind", "artifact");
assert_str_field(artifact, "locator", "artifact");
assert_str_field(artifact, "content_hash", "artifact");
assert_array_field(artifact, "parents", "artifact");
}
#[test]
fn carina_primitive_proposal_has_required_fields() {
let value = load_primitives();
let proposal = primitive(&value, "proposal");
assert_str_field(proposal, "id", "proposal");
assert_str_field(proposal, "kind", "proposal");
assert_object_field(proposal, "target", "proposal");
assert_str_field(
proposal.pointer("/target").unwrap(),
"type",
"proposal.target",
);
assert_str_field(
proposal.pointer("/target").unwrap(),
"id",
"proposal.target",
);
assert_object_field(proposal, "provenance", "proposal");
let provenance = proposal.pointer("/provenance").unwrap();
assert_str_field(provenance, "packet_id", "proposal.provenance");
assert_array_field(provenance, "artifact_ids", "proposal.provenance");
assert_array_field(provenance, "external_object_ids", "proposal.provenance");
assert_str_field(proposal, "status", "proposal");
}
#[test]
fn carina_primitive_diff_has_required_fields() {
let value = load_primitives();
let diff = primitive(&value, "diff");
assert_str_field(diff, "proposal_id", "diff");
assert_object_field(diff, "before", "diff");
assert_object_field(diff, "after", "diff");
assert_array_field(diff, "changed_objects", "diff");
}
#[test]
fn carina_primitive_event_has_required_fields() {
let value = load_primitives();
let event = primitive(&value, "event");
assert_str_field(event, "id", "event");
assert_str_field(event, "kind", "event");
assert_object_field(event, "target", "event");
assert_str_field(event.pointer("/target").unwrap(), "type", "event.target");
assert_str_field(event.pointer("/target").unwrap(), "id", "event.target");
assert_object_field(event, "actor", "event");
assert_str_field(event.pointer("/actor").unwrap(), "id", "event.actor");
assert_str_field(event.pointer("/actor").unwrap(), "type", "event.actor");
assert_str_field(event, "timestamp", "event");
assert_str_field(event, "reason", "event");
assert_object_field(event, "payload", "event");
assert_str_field(
event.pointer("/payload").unwrap(),
"proposal_id",
"event.payload",
);
assert_str_field(
event.pointer("/payload").unwrap(),
"status",
"event.payload",
);
}
#[test]
fn carina_primitive_attestation_has_required_fields() {
let value = load_primitives();
let attestation = primitive(&value, "attestation");
assert_str_field(attestation, "id", "attestation");
assert_object_field(attestation, "actor", "attestation");
assert_str_field(
attestation.pointer("/actor").unwrap(),
"id",
"attestation.actor",
);
assert_str_field(
attestation.pointer("/actor").unwrap(),
"type",
"attestation.actor",
);
assert_object_field(attestation, "target", "attestation");
assert_str_field(
attestation.pointer("/target").unwrap(),
"type",
"attestation.target",
);
assert_str_field(
attestation.pointer("/target").unwrap(),
"id",
"attestation.target",
);
assert_str_field(attestation, "status", "attestation");
assert_str_field(attestation, "scope", "attestation");
}
#[test]
fn carina_primitive_question_has_required_fields() {
let value = load_primitives();
let question = primitive(&value, "question");
assert_str_field(question, "id", "question");
assert_str_field(question, "text", "question");
assert_str_field(question, "rationale", "question");
}
#[test]
fn carina_primitive_protocol_has_required_fields() {
let value = load_primitives();
let protocol = primitive(&value, "protocol");
assert_str_field(protocol, "id", "protocol");
assert_str_field(protocol, "title", "protocol");
assert_array_field(protocol, "produces", "protocol");
}
#[test]
fn carina_primitive_experiment_has_required_fields() {
let value = load_primitives();
let experiment = primitive(&value, "experiment");
assert_str_field(experiment, "id", "experiment");
assert_str_field(experiment, "question_id", "experiment");
assert_str_field(experiment, "protocol_id", "experiment");
assert_str_field(experiment, "intended_update", "experiment");
}
#[test]
fn carina_primitive_mechanism_has_required_fields() {
let value = load_primitives();
let mechanism = primitive(&value, "mechanism");
assert_str_field(mechanism, "id", "mechanism");
assert_str_field(mechanism, "relation", "mechanism");
assert_str_field(mechanism, "shape", "mechanism");
assert_str_field(mechanism, "source_finding_id", "mechanism");
assert_str_field(mechanism, "target_finding_id", "mechanism");
}
#[test]
fn carina_primitive_lineage_has_required_fields() {
let value = load_primitives();
let lineage = primitive(&value, "lineage");
assert_str_field(lineage, "object_id", "lineage");
assert_array_field(lineage, "parents", "lineage");
assert_array_field(lineage, "event_ids", "lineage");
}
#[test]
fn carina_primitive_confidence_has_required_fields() {
let value = load_primitives();
let confidence = primitive(&value, "confidence");
assert_str_field(confidence, "method", "confidence");
assert_str_field(confidence, "scope", "confidence");
assert!(
confidence
.get("score")
.and_then(Value::as_f64)
.is_some_and(|v| (0.0..=1.0).contains(&v)),
"confidence.score must be in [0.0, 1.0]"
);
assert_array_field(confidence, "history", "confidence");
let history = confidence.get("history").and_then(Value::as_array).unwrap();
assert!(
!history.is_empty(),
"confidence.history must record at least one transition"
);
let first = &history[0];
assert_str_field(first, "event_id", "confidence.history[0]");
assert!(
first.get("to").is_some(),
"confidence.history[0].to required (the post-transition score)"
);
}
const EXPECTED_PRIMITIVES_V0_2: &[(&str, &str)] = &[
("finding", "carina.finding.v0.2"),
("evidence", "carina.evidence.v0.2"),
("artifact", "carina.artifact.v0.2"),
("proposal", "carina.proposal.v0.2"),
("diff", "carina.diff.v0.2"),
("event", "carina.event.v0.2"),
("attestation", "carina.attestation.v0.2"),
("question", "carina.question.v0.2"),
("protocol", "carina.protocol.v0.2"),
("experiment", "carina.experiment.v0.2"),
("mechanism", "carina.mechanism.v0.2"),
("lineage", "carina.lineage.v0.2"),
("confidence", "carina.confidence.v0.2"),
];
fn primitives_example_path_v0_2() -> PathBuf {
let manifest_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
manifest_dir
.parent()
.and_then(|p| p.parent())
.expect("crates/vela-protocol parent")
.join("examples/carina-kernel/primitives.v0.2.json")
}
fn load_primitives_v0_2() -> Value {
let path = primitives_example_path_v0_2();
let raw = fs::read_to_string(&path).expect("read v0.2 primitives example");
serde_json::from_str(&raw).expect("parse v0.2 primitives example")
}
#[test]
fn carina_primitives_v0_2_example_exists() {
let path = primitives_example_path_v0_2();
assert!(
path.is_file(),
"Carina v0.2 primitives example missing at {}",
path.display()
);
}
#[test]
fn carina_primitives_v0_2_example_parses() {
let value = load_primitives_v0_2();
assert_eq!(
value.get("schema").and_then(Value::as_str),
Some("carina.examples.v0.2"),
"wrapper schema must be carina.examples.v0.2"
);
let primitives = value
.get("primitives")
.and_then(Value::as_object)
.expect("primitives object");
assert!(
!primitives.is_empty(),
"primitives object must be non-empty"
);
}
#[test]
fn carina_primitives_v0_2_example_covers_every_documented_primitive() {
let value = load_primitives_v0_2();
let primitives = value
.get("primitives")
.and_then(Value::as_object)
.expect("primitives object");
for (key, schema) in EXPECTED_PRIMITIVES_V0_2 {
let entry = primitives
.get(*key)
.unwrap_or_else(|| panic!("Carina v0.2 primitive '{key}' missing"));
let actual_schema = entry
.get("schema")
.and_then(Value::as_str)
.unwrap_or_else(|| panic!("v0.2 primitive '{key}' is missing 'schema' field"));
assert_eq!(
actual_schema, *schema,
"v0.2 primitive '{key}' must declare schema '{schema}'"
);
}
}
#[test]
fn carina_primitive_v0_2_proposal_carries_actor() {
let value = load_primitives_v0_2();
let proposal = value
.pointer("/primitives/proposal")
.expect("v0.2 proposal primitive");
assert_str_field(proposal, "id", "proposal");
assert_str_field(proposal, "kind", "proposal");
assert_object_field(proposal, "target", "proposal");
assert_object_field(proposal, "actor", "proposal");
let actor = proposal.pointer("/actor").unwrap();
assert_str_field(actor, "id", "proposal.actor");
assert_str_field(actor, "type", "proposal.actor");
assert_object_field(proposal, "provenance", "proposal");
let provenance = proposal.pointer("/provenance").unwrap();
assert_str_field(provenance, "packet_id", "proposal.provenance");
assert_array_field(provenance, "artifact_ids", "proposal.provenance");
assert_array_field(provenance, "external_object_ids", "proposal.provenance");
assert_str_field(proposal, "status", "proposal");
}
fn load_primitives_v0_3() -> Value {
let path = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("../../examples/carina-kernel/primitives.v0.3.json");
let text = std::fs::read_to_string(&path).expect("read v0.3 primitives example");
serde_json::from_str(&text).expect("parse v0.3 primitives example")
}
#[test]
fn carina_v0_3_aggregate_round_trips_all_14_schemas() {
use vela_protocol::carina_validate;
let value = load_primitives_v0_3();
let primitives = value
.get("primitives")
.and_then(Value::as_object)
.expect("v0.3 aggregate has `primitives`");
let v0_3_names = [
"finding",
"evidence",
"artifact",
"proposal",
"diff",
"event",
"attestation",
"question",
"protocol",
"experiment",
"mechanism",
"lineage",
"confidence",
"proof",
];
for name in v0_3_names {
assert!(
primitives.contains_key(name),
"v0.3 example missing primitive {name}"
);
}
for (name, v) in primitives {
carina_validate::validate(name, v)
.unwrap_or_else(|errs| panic!("primitive {name} failed: {:#?}", errs));
}
}
#[test]
fn carina_v0_3_proof_primitive_carries_gowers_shape() {
let value = load_primitives_v0_3();
let proof = value
.pointer("/primitives/proof")
.expect("v0.3 example carries proof primitive");
for required in [
"id",
"tool",
"tool_version",
"script_locator",
"verifier_output_hash",
"verified_at",
"target_finding_id",
] {
assert!(
proof.get(required).is_some(),
"proof primitive missing field '{required}'"
);
}
let tool = proof
.get("tool")
.and_then(Value::as_str)
.expect("proof.tool is a string");
assert!(
[
"lean4", "coq", "isabelle", "agda", "metamath", "rocq", "other"
]
.contains(&tool),
"proof.tool '{tool}' not in enumerated tools"
);
}
#[test]
fn carina_event_payload_validator_agrees_with_schema() {
use vela_protocol::carina_validate;
use vela_protocol::events::validate_event_payload;
let kind = "finding.reviewed";
let payload = json!({
"proposal_id": "vpr_abc",
"status": "accepted"
});
validate_event_payload(kind, &payload).expect("rust event-payload validator accepts payload");
let event = json!({
"schema": "carina.event.v0.3",
"id": "vev_abc",
"kind": kind,
"target": {"type": "finding", "id": "vf_abc"},
"actor": {"id": "reviewer:demo", "type": "human"},
"timestamp": "2026-05-09T00:00:00Z",
"reason": "demo",
"payload": payload,
});
carina_validate::validate("event", &event).expect("v0.3 event schema accepts the same shape");
}
fn load_primitives_v0_4() -> Value {
let path = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("../../examples/carina-kernel/primitives.v0.4.json");
let text = std::fs::read_to_string(&path).expect("read v0.4 primitives example");
serde_json::from_str(&text).expect("parse v0.4 primitives example")
}
#[test]
fn carina_v0_4_aggregate_round_trips_all_15_schemas() {
use vela_protocol::carina_validate;
let value = load_primitives_v0_4();
assert_eq!(
value.get("schema").and_then(Value::as_str),
Some("carina.examples.v0.4"),
"v0.4 wrapper schema must be carina.examples.v0.4"
);
let primitives = value
.get("primitives")
.and_then(Value::as_object)
.expect("v0.4 aggregate has `primitives`");
let v0_4_names = [
"finding",
"evidence",
"artifact",
"proposal",
"diff",
"event",
"attestation",
"question",
"protocol",
"experiment",
"mechanism",
"lineage",
"confidence",
"proof",
"atlas",
];
for name in v0_4_names {
assert!(
primitives.contains_key(name),
"v0.4 example missing primitive {name}"
);
}
for (name, v) in primitives {
carina_validate::validate(name, v)
.unwrap_or_else(|errs| panic!("primitive {name} failed: {:#?}", errs));
}
}
#[test]
fn carina_v0_4_atlas_composes_brain_tumor_and_anti_amyloid() {
let value = load_primitives_v0_4();
let atlas = value
.pointer("/primitives/atlas")
.expect("v0.4 example carries atlas primitive");
assert_eq!(
atlas.get("name").and_then(Value::as_str),
Some("Brain Tumor Translation")
);
assert_eq!(
atlas.get("domain").and_then(Value::as_str),
Some("oncology")
);
let composing = atlas
.get("composing_frontiers")
.and_then(Value::as_array)
.expect("Atlas has composing_frontiers array");
assert!(
composing.len() >= 2,
"Atlas must compose at least 2 frontiers"
);
let names: Vec<&str> = composing
.iter()
.filter_map(|v| v.get("name").and_then(Value::as_str))
.collect();
assert!(names.contains(&"brain-tumor-translation"));
assert!(names.contains(&"anti-amyloid-translation"));
}
fn load_primitives_v0_5() -> Value {
let path = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("../../examples/carina-kernel/primitives.v0.5.json");
let text = std::fs::read_to_string(&path).expect("read v0.5 primitives example");
serde_json::from_str(&text).expect("parse v0.5 primitives example")
}
#[test]
fn carina_v0_5_aggregate_round_trips_all_16_schemas() {
use vela_protocol::carina_validate;
let value = load_primitives_v0_5();
assert_eq!(
value.get("schema").and_then(Value::as_str),
Some("carina.examples.v0.5"),
"v0.5 wrapper schema must be carina.examples.v0.5"
);
let primitives = value
.get("primitives")
.and_then(Value::as_object)
.expect("v0.5 aggregate has `primitives`");
for name in carina_validate::PRIMITIVE_NAMES {
assert!(
primitives.contains_key(*name),
"v0.5 example missing primitive {name}"
);
}
for (name, v) in primitives {
carina_validate::validate(name, v)
.unwrap_or_else(|errs| panic!("primitive {name} failed: {:#?}", errs));
}
}
#[test]
fn carina_v0_5_constellation_composes_atlases() {
let value = load_primitives_v0_5();
let constellation = value
.pointer("/primitives/constellation")
.expect("v0.5 example carries constellation primitive");
let composing = constellation
.get("composing_atlases")
.and_then(Value::as_array)
.expect("constellation has composing_atlases");
assert!(!composing.is_empty());
for atlas in composing {
let vat_id = atlas
.get("vat_id")
.and_then(Value::as_str)
.expect("composing atlas has vat_id");
assert!(
vat_id.starts_with("vat_"),
"composing atlas vat_id must start with vat_: {vat_id}"
);
}
}