use std::path::Path;
mod common;
fn flow_graphs(dir: &Path) -> serde_json::Value {
let out = common::run_ok(dir, &["export", "flow-graphs.json"]);
let v: serde_json::Value = serde_json::from_str(&out).expect("flow-graphs.json parses");
assert!(v.is_array() && !v.as_array().unwrap().is_empty(), "fixture yields flow graphs");
v
}
#[test]
fn native_same_file_calls_yield_sequence_flow_with_extracted_steps() {
let repo = common::copy_fixture("behavior-native");
let dir = common::workdir(repo.path());
common::run_ok(&dir, &["index", "--quiet"]);
let graphs = flow_graphs(&dir);
let graphs = graphs.as_array().unwrap();
let graph = graphs
.iter()
.find(|g| g["name"].as_str() == Some("run"))
.unwrap_or_else(|| panic!("flow graph for `run` exists: {}", serde_json::to_string(&graphs).unwrap()));
let nodes = graph["nodes"].as_array().unwrap();
let ops: Vec<&str> = nodes
.iter()
.filter_map(|n| n["operation"].as_str())
.collect();
for want in ["run", "handle", "normalize", "validate", "parse"] {
assert!(
ops.iter().any(|o| o.ends_with(want)),
"flow graph reaches {want}: {ops:?}"
);
}
let edges = graph["edges"].as_array().unwrap();
assert!(
edges.iter().any(|e| e["provenance"] == "EXTRACTED"),
"native call edges carry EXTRACTED provenance: {}",
serde_json::to_string(&edges).unwrap()
);
let run_idx = nodes
.iter()
.position(|n| n["operation"].as_str().map(|o| o.ends_with("run")).unwrap_or(false))
.unwrap();
let handle_idx = nodes
.iter()
.position(|n| n["operation"].as_str().map(|o| o.ends_with("handle")).unwrap_or(false))
.unwrap();
let run_handle = edges
.iter()
.find(|e| e["from"] == run_idx && e["to"] == handle_idx)
.unwrap_or_else(|| panic!("run -> handle edge exists: {}", serde_json::to_string(&edges).unwrap()));
assert_eq!(
run_handle["provenance"], "EXTRACTED",
"same-file native call is EXTRACTED evidence"
);
let call_edges_resolved: Vec<&serde_json::Value> = edges
.iter()
.filter(|e| e["kind"] == "next" && e["provenance"] == "RESOLVED")
.collect();
assert!(
call_edges_resolved.is_empty(),
"no resolved call edges without a language server: {:?}",
call_edges_resolved
);
}
#[test]
fn atlas_flows_section_shows_native_chain() {
let repo = common::copy_fixture("behavior-native");
let dir = common::workdir(repo.path());
common::run_ok(&dir, &["index", "--quiet"]);
let atlas = common::run_ok(&dir, &["atlas"]);
let flows = atlas
.split("FLOWS")
.nth(1)
.unwrap_or_default()
.split("STATE & DATA AUTHORITY")
.next()
.unwrap_or_default();
assert!(
flows.contains("run [sequence]"),
"FLOWS section lists the native run flow: {flows}"
);
for step in ["handle", "normalize", "validate", "parse"] {
assert!(
flows.contains(step),
"FLOWS section shows the {step} step: {flows}"
);
}
assert!(
flows.contains("root: run") && flows.contains("-> root: handle"),
"run -> handle chain rendered from native evidence: {flows}"
);
}