use super::*;
#[test]
fn a_merged_elicitation_marker_is_outside_the_chain_and_takes_no_one_with_it() {
let r = recs(&[
&u("u0", "", "start the work", "2026-06-07T05:00:00.000Z"),
&a("a0", "u0", "working", "2026-06-07T05:00:05.000Z"),
r#"{"type":"assistant","uuid":"e-toolu_1","timestamp":"2026-06-07T05:00:30.000Z","message":{"role":"assistant","stop_reason":"tool_use","content":[{"type":"tool_use","id":"toolu_1","name":"AskUserQuestion","input":{"questions":[{"question":"deploy now?"}]}}]},"csift":"elicitation-marker-v1","csiftPhase":"pending","csiftKind":"AskUserQuestion","csiftKey":"toolu_1"}"#,
]);
let c = Chain::build(&r, None);
assert_eq!(
survivals(&c, r.len()),
vec!["live", "live", "live"],
"the axis says nothing about a merged marker, and nothing about it moves the rest"
);
assert_eq!(c.leaf_index, Some(1), "the leaf is the real tail record");
assert_eq!(c.abandoned_records, 0);
}
#[test]
fn a_boundary_the_walk_cannot_climb_crosses_the_cut_through_its_logical_parent() {
let r = recs(&[
&u("u0", "", "chart the lagoon", "2026-06-07T05:00:00.000Z"),
&a("a0", "u0", "charting", "2026-06-07T05:00:05.000Z"),
&u("u2", "u0", "survey the shoal", "2026-06-07T05:00:10.000Z"),
&a("a2", "u2", "surveying", "2026-06-07T05:00:15.000Z"),
r#"{"type":"system","subtype":"compact_boundary","uuid":"b1","parentUuid":"deleted-from-disk","logicalParentUuid":"a0","timestamp":"2026-06-07T05:10:00.000Z","compactMetadata":{"trigger":"auto","preTokens":900}}"#,
&u("u1", "b1", "dredge the channel", "2026-06-07T05:11:00.000Z"),
&a("a1", "u1", "dredging", "2026-06-07T05:11:05.000Z"),
]);
let c = Chain::build(&r, None);
assert_eq!(c.boundary_cut, Some(4), "the crossing still names the cut");
assert_eq!(
survivals(&c, r.len()),
vec![
"pre-cut",
"pre-cut",
"abandoned",
"abandoned",
"live",
"live",
"live"
],
"the crossed history is read and flagged; the branch off it is resolved as abandoned"
);
assert_eq!(c.abandoned_records, 2);
assert_eq!(c.rewound_turns, 1, "the abandoned opener drew a reply");
assert!(
matches!(c.kind(2), Some(Kind::Rewound { .. })),
"an answered abandoned opener above the cut is a rewind, not a draft"
);
}