use std::path::{Path, PathBuf};
use toolpath::v1::Graph;
use toolpath_codex::project::CodexProjector;
use toolpath_codex::{RolloutReader, to_view};
use toolpath_convo::{
ConversationProjector, ConversationView, DeriveConfig, derive_path, extract_conversation,
};
fn fixture_path() -> PathBuf {
Path::new(env!("CARGO_MANIFEST_DIR"))
.join("tests")
.join("fixtures")
.join("compacted_session.jsonl")
}
fn load_view() -> ConversationView {
let session = RolloutReader::read_session(fixture_path()).expect("read fixture");
to_view(&session)
}
fn ir_roundtrip(view: &ConversationView) -> ConversationView {
let path = derive_path(view, &DeriveConfig::default());
let graph = Graph::from_path(path);
let json = graph.to_json().expect("serialize Graph");
let back = Graph::from_json(&json).expect("parse Graph");
let path = back.into_single_path().expect("single path");
extract_conversation(&path)
}
#[test]
fn fixture_loads_without_panic() {
let view = load_view();
assert!(
!view.turns.is_empty(),
"compaction fixture should produce turns"
);
}
#[test]
fn pre_compact_content_survives_roundtrip() {
let original = load_view();
let after = ir_roundtrip(&original);
let needles = ["refactor the auth module", "reading the current auth code"];
for n in needles {
assert!(
original.turns.iter().any(|t| t.text.contains(n)),
"pre-compact text {n:?} missing from initial view"
);
assert!(
after.turns.iter().any(|t| t.text.contains(n)),
"pre-compact text {n:?} dropped after roundtrip"
);
}
}
#[test]
fn post_compact_content_survives_roundtrip() {
let original = load_view();
let after = ir_roundtrip(&original);
let needles = [
"now add session validation",
"added session validation to login()",
];
for n in needles {
assert!(
original.turns.iter().any(|t| t.text.contains(n)),
"post-compact text {n:?} missing from initial view"
);
assert!(
after.turns.iter().any(|t| t.text.contains(n)),
"post-compact text {n:?} dropped after roundtrip"
);
}
}
#[test]
fn projector_output_is_re_parseable_by_reader() {
let view = load_view();
let after = ir_roundtrip(&view);
let projector = CodexProjector::new();
let session = projector.project(&after).expect("project");
let mut lines: Vec<String> = Vec::new();
for line in &session.lines {
lines.push(serde_json::to_string(line).expect("serialize rollout line"));
}
let tmp = tempfile::Builder::new()
.suffix(".jsonl")
.tempfile()
.expect("tempfile");
std::fs::write(tmp.path(), lines.join("\n")).expect("write tempfile");
RolloutReader::read_session(tmp.path()).expect("re-read projected JSONL");
}