use std::collections::BTreeMap;
use std::path::PathBuf;
use ant_types::{
AuthorStamp, Belief, BeliefId, Edge, EdgeId, Evidence, EvidenceId, Observation, ObservationId,
ProjectId, PropertyValue, SubjectType, TenantId, TypeName, UserId, Vertex, VertexId,
};
use antares_format::{
AntRecord, AntWriter, Counts, Manifest, Tombstone, VectorRecord, FORMAT_VERSION,
};
use sha2::{Digest, Sha256};
fn manifest() -> Manifest {
Manifest {
format: "antares".into(),
version: FORMAT_VERSION.into(),
tenant_id: 1,
project_id: 1,
selection: Some(serde_json::json!({"kind": "whole_scope"})),
created_at: Some("2026-08-10T00:00:00Z".parse().unwrap()),
producer: Some("openantares-conformance/0.1".into()),
}
}
fn out_dir() -> PathBuf {
match std::env::var_os("ANT_CONFORMANCE_GOLDEN") {
Some(dir) => PathBuf::from(dir),
None => {
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../../openantares/conformance/golden")
}
}
}
fn basic() -> Vec<u8> {
let mut props = BTreeMap::new();
props.insert("amount".into(), PropertyValue::Long(48000));
props.insert("stage".into(), PropertyValue::Text("proposal".into()));
props.insert(
"meta".into(),
PropertyValue::Json(serde_json::json!({"nested": [1, 2], "flag": true})),
);
props.insert(
"exact_amount".into(),
PropertyValue::Decimal(ant_types::Decimal::parse("12345678901234567.89").unwrap()),
);
props.insert(
"closed_on".into(),
PropertyValue::Date(chrono::NaiveDate::from_ymd_opt(2026, 8, 10).unwrap()),
);
props.insert(
"review_at".into(),
PropertyValue::Time(chrono::NaiveTime::from_hms_micro_opt(14, 30, 0, 500_000).unwrap()),
);
props.insert(
"signed_at".into(),
PropertyValue::Timestamp(
chrono::DateTime::parse_from_rfc3339("2026-08-10T09:00:00+02:00").unwrap(),
),
);
props.insert(
"external_id".into(),
PropertyValue::Uuid(uuid::Uuid::parse_str("6ba7b810-9dad-11d1-80b4-00c04fd430c8").unwrap()),
);
props.insert(
"seal".into(),
PropertyValue::Bytes(vec![0x00, 0x01, 0xfe, 0xff]),
);
props.insert("headcount".into(), PropertyValue::Int32(1200));
props.insert("region_code".into(), PropertyValue::Int16(-7));
props.insert(
"tags".into(),
PropertyValue::Array(vec![
PropertyValue::Text("enterprise".into()),
PropertyValue::Text("renewal".into()),
]),
);
let deal = Vertex {
id: VertexId("deal_1".into()),
name: "Hooli Enterprise Proposal".into(),
label: TypeName("Antares.Deal".into()),
properties: props,
};
let company = Vertex {
id: VertexId("acct_1".into()),
name: "Hooli Corp".into(),
label: TypeName("Antares.Company".into()),
properties: BTreeMap::new(),
};
let edge = Edge {
id: EdgeId("deal_1->acct_1:belongsTo".into()),
src: VertexId("deal_1".into()),
src_type: TypeName("Antares.Deal".into()),
dst: VertexId("acct_1".into()),
dst_type: TypeName("Antares.Company".into()),
label: "belongsTo".into(),
properties: BTreeMap::new(),
valid_from: None,
valid_to: None,
observed_at: None,
extracted_at: None,
confidence: Some(1.0),
evidenced_by: vec![EvidenceId("ev_1".into())],
};
let evidence = Evidence {
id: EvidenceId("ev_1".into()),
tenant_id: TenantId(1),
project_id: ProjectId(1),
source_uri: "antares://mail/9".into(),
source_type: "email".into(),
source_id: "mail-9".into(),
content: "we moved the deal to proposal stage after the demo call".into(),
char_start: None,
char_end: None,
byte_start: None,
byte_end: None,
observed_at: Some("2026-08-09T10:00:00Z".parse().unwrap()),
extracted_at: Some("2026-08-09T10:00:01Z".parse().unwrap()),
extractor_version: Some("conformance/1".into()),
confidence: None,
metadata: serde_json::Value::Null,
author: None,
};
let obs = Observation {
id: ObservationId("obs_1".into()),
tenant_id: TenantId(1),
project_id: ProjectId(1),
source_event_id: Some("mail-9".into()),
source_uri: Some("antares://mail/9".into()),
subject_id: Some(VertexId("deal_1".into())),
predicate: "stage_change".into(),
object_id: None,
object_value: Some(serde_json::json!("proposal")),
observed_at: "2026-08-09T10:00:00Z".parse().unwrap(),
extracted_at: "2026-08-09T10:00:01Z".parse().unwrap(),
confidence: Some(0.9),
evidence_ids: vec![EvidenceId("ev_1".into())],
extractor_version: Some("conformance/1".into()),
metadata: serde_json::Value::Null,
author: None,
};
let belief = Belief {
id: BeliefId("bel_1".into()),
tenant_id: TenantId(1),
project_id: ProjectId(1),
subject_id: VertexId("deal_1".into()),
predicate: "stage".into(),
value_json: serde_json::json!("proposal"),
confidence: Some(0.9),
belief_version: 1,
derived_from: vec![ObservationId("obs_1".into())],
evidence_ids: vec![EvidenceId("ev_1".into())],
valid_from: None,
valid_to: None,
observed_at: Some("2026-08-09T10:00:00Z".parse().unwrap()),
updated_at: "2026-08-09T10:00:02Z".parse().unwrap(),
decay_policy: None,
metadata: serde_json::Value::Null,
author: None,
contributing_authors: Vec::new(),
};
let vector = VectorRecord {
record_type: "Evidence".into(),
record_id: "ev_1".into(),
label: "Antares.Chunk".into(),
field: "content".into(),
vector: vec![0.25, -0.5, 0.125],
text_preview: Some("we moved the deal".into()),
evidence_ids: vec!["ev_1".into()],
};
let mut w = AntWriter::new(Vec::new(), manifest(), 0).expect("writer");
w.write(AntRecord::Vertex { data: deal }).unwrap();
w.write(AntRecord::Vertex { data: company }).unwrap();
w.write(AntRecord::Edge { data: edge }).unwrap();
w.write(AntRecord::Observation { data: obs }).unwrap();
w.write(AntRecord::Evidence { data: evidence }).unwrap();
w.write(AntRecord::Belief { data: belief }).unwrap();
w.write(AntRecord::Vector { data: vector }).unwrap();
w.finish().expect("finish")
}
fn forward_compat() -> Vec<u8> {
let m = serde_json::to_string(&AntRecord::Manifest(manifest())).unwrap();
let v = serde_json::to_string(&AntRecord::Vertex {
data: Vertex {
id: VertexId("v_known".into()),
name: "Known".into(),
label: TypeName("Antares.Deal".into()),
properties: BTreeMap::new(),
},
})
.unwrap();
let unknown = r#"{"kind":"hologram","data":{"future":true}}"#;
let mut hasher = Sha256::new();
for line in [m.as_str(), v.as_str(), unknown] {
hasher.update(line.as_bytes());
hasher.update(b"\n");
}
let trailer = AntRecord::Trailer {
counts: Counts {
vertices: 1,
..Default::default()
},
sha256: format!("{:x}", hasher.finalize()),
};
let t = serde_json::to_string(&trailer).unwrap();
let raw = format!("{m}\n{v}\n{unknown}\n{t}\n");
zstd::stream::encode_all(raw.as_bytes(), 0).unwrap()
}
fn tombstones() -> Vec<u8> {
let live = Vertex {
id: VertexId("deal_live".into()),
name: "Still Here".into(),
label: TypeName("Antares.Deal".into()),
properties: BTreeMap::new(),
};
let edge = Edge {
id: EdgeId("deal_live->acct_1:belongsTo".into()),
src: VertexId("deal_live".into()),
src_type: TypeName("Antares.Deal".into()),
dst: VertexId("acct_1".into()),
dst_type: TypeName("Antares.Company".into()),
label: "belongsTo".into(),
properties: BTreeMap::new(),
valid_from: None,
valid_to: None,
observed_at: None,
extracted_at: None,
confidence: None,
evidenced_by: Vec::new(),
};
let vtomb = Tombstone {
id: "deal_gone".into(),
deleted_at: "2026-08-10T09:15:00Z".parse().unwrap(),
author: Some(AuthorStamp {
user_id: UserId("u_42".into()),
token_id: None,
subject_type: SubjectType::User,
authored_at: "2026-08-10T09:15:00Z".parse().unwrap(),
}),
};
let etomb = Tombstone {
id: "deal_gone->acct_1:belongsTo".into(),
deleted_at: "2026-08-10T09:15:00Z".parse().unwrap(),
author: None,
};
let mut w = AntWriter::new(Vec::new(), manifest(), 0).expect("writer");
w.write(AntRecord::Vertex { data: live }).unwrap();
w.write(AntRecord::Edge { data: edge }).unwrap();
w.write(AntRecord::VertexTombstone { data: vtomb }).unwrap();
w.write(AntRecord::EdgeTombstone { data: etomb }).unwrap();
w.finish().expect("finish")
}
fn major_version() -> Vec<u8> {
let mut m = manifest();
m.version = "1.0".into();
let m = serde_json::to_string(&AntRecord::Manifest(m)).unwrap();
let v = serde_json::to_string(&AntRecord::Vertex {
data: Vertex {
id: VertexId("v_future".into()),
name: "From A Later Major".into(),
label: TypeName("Antares.Deal".into()),
properties: BTreeMap::new(),
},
})
.unwrap();
let mut hasher = Sha256::new();
for line in [m.as_str(), v.as_str()] {
hasher.update(line.as_bytes());
hasher.update(b"\n");
}
let trailer = AntRecord::Trailer {
counts: Counts {
vertices: 1,
..Default::default()
},
sha256: format!("{:x}", hasher.finalize()),
};
let t = serde_json::to_string(&trailer).unwrap();
let raw = format!("{m}\n{v}\n{t}\n");
zstd::stream::encode_all(raw.as_bytes(), 0).unwrap()
}
fn main() {
let dir = out_dir();
std::fs::create_dir_all(&dir).expect("mkdir golden");
std::fs::write(dir.join("basic.ant"), basic()).expect("write basic.ant");
std::fs::write(dir.join("forward_compat.ant"), forward_compat())
.expect("write forward_compat.ant");
std::fs::write(dir.join("tombstones.ant"), tombstones()).expect("write tombstones.ant");
std::fs::write(dir.join("major_version.ant"), major_version())
.expect("write major_version.ant");
let expected = serde_json::json!({
"basic.ant": {
"version": FORMAT_VERSION,
"tenantId": 1,
"projectId": 1,
"counts": {"schemaTypes": 0, "vertices": 2, "edges": 1,
"observations": 1, "evidence": 1, "beliefs": 1, "vectors": 1,
"vertexTombstones": 0, "edgeTombstones": 0},
"recordKinds": ["vertex", "vertex", "edge", "observation",
"evidence", "belief", "vector"],
"firstVertexId": "deal_1"
},
"forward_compat.ant": {
"version": FORMAT_VERSION,
"tenantId": 1,
"projectId": 1,
"counts": {"schemaTypes": 0, "vertices": 1, "edges": 0,
"observations": 0, "evidence": 0, "beliefs": 0, "vectors": 0,
"vertexTombstones": 0, "edgeTombstones": 0},
"recordKinds": ["vertex"],
"skippedKinds": ["hologram"]
},
"tombstones.ant": {
"version": FORMAT_VERSION,
"tenantId": 1,
"projectId": 1,
"counts": {"schemaTypes": 0, "vertices": 1, "edges": 1,
"observations": 0, "evidence": 0, "beliefs": 0, "vectors": 0,
"vertexTombstones": 1, "edgeTombstones": 1},
"recordKinds": ["vertex", "edge", "vertex_tombstone", "edge_tombstone"],
"firstVertexId": "deal_live"
}
});
std::fs::write(
dir.join("expected.json"),
serde_json::to_string_pretty(&expected).unwrap(),
)
.expect("write expected.json");
let negatives = serde_json::json!({
"major_version.ant": {
"mustReject": true,
"why": "declares format v1.0; a 0.x reader must refuse rather than \
misread, because a major bump means field meanings or the \
container framing changed. Valid in every other respect, so \
rejecting it for any other reason is the wrong pass."
}
});
std::fs::write(
dir.join("expected_negatives.json"),
serde_json::to_string_pretty(&negatives).unwrap(),
)
.expect("write expected_negatives.json");
eprintln!("wrote goldens to {}", dir.display());
}