use super::*;
fn spine_at(line: usize) -> crate::parse::SpineRow {
let raw = format!(
r#"{{"type":"attachment","uuid":"x{line}","parentUuid":"p{line}","timestamp":"2026-06-07T05:00:00.000Z","attachment":{{"type":"hook_additional_context","content":["ctx"]}}}}"#
);
crate::parse::spine_record(line, raw.as_bytes()).expect("an attachment lifts a spine row")
}
fn kept_at(line: usize) -> Kept {
Kept {
rec: rec(&format!(
r#"{{"type":"user","uuid":"u{line}","timestamp":"2026-06-07T05:00:00.000Z","message":{{"role":"user","content":"row {line}"}}}}"#
)),
can_hit: true,
line_no: line,
from_sidecar: line == 0,
}
}
fn row_lines(rows: &[Row<'_>]) -> Vec<usize> {
rows.iter().map(|r| Row::line_no(*r)).collect()
}
#[test]
fn merge_spine_interleaves_the_scanned_and_demoted_streams_by_line() {
let scanned: Vec<_> = [2usize, 4, 9].into_iter().map(spine_at).collect();
let demoted: Vec<_> = [1usize, 5, 7].into_iter().map(spine_at).collect();
let out = merge_spine(scanned, demoted);
assert_eq!(
out.iter()
.map(crate::parse::SpineRow::line)
.collect::<Vec<_>>(),
vec![1, 2, 4, 5, 7, 9]
);
}
#[test]
fn merge_spine_handles_a_stream_that_runs_out_first() {
let scanned: Vec<_> = [1usize, 2].into_iter().map(spine_at).collect();
let demoted: Vec<_> = [8usize, 9, 10].into_iter().map(spine_at).collect();
let out = merge_spine(scanned, demoted);
assert_eq!(
out.iter()
.map(crate::parse::SpineRow::line)
.collect::<Vec<_>>(),
vec![1, 2, 8, 9, 10]
);
}
#[test]
fn merge_rows_puts_records_and_spine_rows_in_file_order() {
let records = vec![kept_at(5), kept_at(7)];
let spine = vec![spine_at(2), spine_at(6)];
let out = merge_rows(&records, &spine);
assert_eq!(row_lines(&out), vec![2, 5, 6, 7]);
assert!(out[0].kept().is_none(), "L2 is a chain-only spine row");
assert!(out[1].kept().is_some(), "L5 is a searchable record");
assert!(out[2].kept().is_none(), "L6 is a chain-only spine row");
assert!(out[3].kept().is_some(), "L7 is a searchable record");
}
#[test]
fn a_sidecar_record_lands_after_every_scanned_row() {
let records = vec![kept_at(2), kept_at(0)];
let spine = vec![spine_at(5)];
let out = merge_rows(&records, &spine);
assert_eq!(row_lines(&out), vec![2, 5, 0]);
assert!(
out[2].kept().is_some_and(|k| k.from_sidecar),
"the line-less record is last, not first"
);
}