use crate::harness::*;
const ENC: &str = "-Users-dev-example-project";
const SESSION: &str = "11111111-2222-4333-8444-555555555555";
fn bg(uuid: &str, ts: &str, text: &str) -> String {
format!(
r#"{{"type":"user","uuid":"{uuid}","timestamp":"{ts}","sessionKind":"bg","message":{{"role":"user","content":"{text}"}}}}"#
)
}
fn fg(uuid: &str, ts: &str, text: &str) -> String {
format!(
r#"{{"type":"user","uuid":"{uuid}","timestamp":"{ts}","message":{{"role":"user","content":"{text}"}}}}"#
)
}
fn fg_agent(uuid: &str, ts: &str, text: &str) -> String {
format!(
r#"{{"type":"assistant","uuid":"{uuid}","timestamp":"{ts}","message":{{"role":"assistant","content":[{{"type":"text","text":"{text}"}}]}}}}"#
)
}
fn session_row(out: &Output) -> serde_json::Value {
out.stdout
.lines()
.filter_map(|l| serde_json::from_str(l).ok())
.find(|v: &serde_json::Value| v["kind"] == "session")
.expect("session row")
}
fn handed_back_jsonl() -> String {
format!(
"{}\n{}\n{}\n{}\n",
bg("u1", "2026-06-07T05:00:00.000Z", "run in the background"),
bg("u2", "2026-06-07T05:01:00.000Z", "still in the background"),
fg(
"u3",
"2026-06-07T06:00:00.000Z",
"resumed in the foreground"
),
fg("u4", "2026-06-07T06:01:00.000Z", "and again"),
)
}
#[test]
fn the_lane_row_names_the_values_and_says_the_span_needs_the_flag() {
let h = Home::new();
h.write(&format!("{ENC}/{SESSION}.jsonl"), &handed_back_jsonl());
let out = h.run(&["list", &format!("@{SESSION}")]);
assert!(out.success, "stderr: {}", out.stderr);
assert!(
out.stdout
.contains("lane bg (seen in the head/tail windows; span needs --lineage)"),
"the default row names the value and points at the flag for the span:\n{}",
out.stdout
);
let row = session_row(&h.run(&["list", &format!("@{SESSION}"), "--format", "json"]));
assert_eq!(row["session_kind"], serde_json::json!(["bg"]), "{row}");
assert!(row["session_kind_first_line"].is_null(), "{row}");
assert!(row["session_kind_last_line"].is_null(), "{row}");
assert_eq!(row["lineage_scanned"], false, "{row}");
}
#[test]
fn lineage_reports_the_span_the_windows_cannot_see() {
let h = Home::new();
h.write(&format!("{ENC}/{SESSION}.jsonl"), &handed_back_jsonl());
let out = h.run(&["list", &format!("@{SESSION}"), "--lineage"]);
assert!(out.success, "stderr: {}", out.stderr);
assert!(
out.stdout.contains("lane bg on L1..L2"),
"the stamp covers lines 1 and 2 and stops where the foreground resume begins:\n{}",
out.stdout
);
let row = session_row(&h.run(&[
"list",
&format!("@{SESSION}"),
"--lineage",
"--format",
"json",
]));
assert_eq!(row["session_kind"], serde_json::json!(["bg"]), "{row}");
assert_eq!(row["session_kind_first_line"], 1, "{row}");
assert_eq!(row["session_kind_last_line"], 2, "{row}");
assert_eq!(row["lineage_scanned"], true, "{row}");
}
#[test]
fn a_foreground_session_carries_no_lane_row_at_all() {
let h = Home::new();
h.write(
&format!("{ENC}/{SESSION}.jsonl"),
&format!("{}\n", fg("u1", "2026-06-07T05:00:00.000Z", "hello")),
);
let out = h.run(&["list", &format!("@{SESSION}"), "--lineage"]);
assert!(
!out.stdout.contains("lane "),
"no stamp, no row:\n{}",
out.stdout
);
let row = session_row(&h.run(&[
"list",
&format!("@{SESSION}"),
"--lineage",
"--format",
"json",
]));
assert_eq!(
row["session_kind"].as_array().map(Vec::len),
Some(0),
"{row}"
);
assert!(row["session_kind_first_line"].is_null(), "{row}");
assert_eq!(row["lineage_scanned"], true, "{row}");
}
#[test]
fn a_stamp_only_in_the_middle_is_invisible_to_the_windows_and_found_by_the_flag() {
let h = Home::new();
let mut body = String::new();
body.push_str(&format!(
"{}\n",
fg("u1", "2026-06-07T05:00:00.000Z", "foreground opener")
));
body.push_str(&format!(
"{}\n",
bg("u2", "2026-06-07T05:10:00.000Z", "handed to the background")
));
for i in 0..40 {
body.push_str(&format!(
"{}\n",
fg(
&format!("t{i}"),
"2026-06-07T06:00:00.000Z",
"back in the foreground"
)
));
body.push_str(&format!(
"{}\n",
fg_agent(&format!("a{i}"), "2026-06-07T06:00:01.000Z", "acknowledged")
));
}
h.write(&format!("{ENC}/{SESSION}.jsonl"), &body);
let plain = session_row(&h.run(&["list", &format!("@{SESSION}"), "--format", "json"]));
assert_eq!(
plain["session_kind"].as_array().map(Vec::len),
Some(0),
"the windows never reach the middle carrier: {plain}"
);
let scanned = session_row(&h.run(&[
"list",
&format!("@{SESSION}"),
"--lineage",
"--format",
"json",
]));
assert_eq!(
scanned["session_kind"],
serde_json::json!(["bg"]),
"{scanned}"
);
assert_eq!(scanned["session_kind_first_line"], 2, "{scanned}");
assert_eq!(scanned["session_kind_last_line"], 2, "{scanned}");
}
#[test]
fn lineage_also_resolves_a_handoff_line_the_tail_window_lost() {
let h = Home::new();
let child = "99999999-2222-4333-8444-555555555555";
let mut body = String::new();
body.push_str(&format!(
"{}\n",
fg("u1", "2026-06-07T05:00:00.000Z", "before the handoff")
));
body.push_str(&format!(
r#"{{"type":"continued-in","timestamp":"2026-06-07T05:10:00.000Z","sessionId":"{SESSION}","continuedInSessionId":"{child}"}}"#
));
body.push('\n');
for i in 0..40 {
body.push_str(&format!(
"{}\n",
fg(
&format!("t{i}"),
"2026-06-07T06:00:00.000Z",
"resumed after the handoff"
)
));
body.push_str(&format!(
"{}\n",
fg_agent(&format!("a{i}"), "2026-06-07T06:00:01.000Z", "acknowledged")
));
}
h.write(&format!("{ENC}/{SESSION}.jsonl"), &body);
let plain = session_row(&h.run(&["list", &format!("@{SESSION}"), "--format", "json"]));
assert!(
plain["continued_in"].is_null(),
"the documented window limit: {plain}"
);
let scanned = session_row(&h.run(&[
"list",
&format!("@{SESSION}"),
"--lineage",
"--format",
"json",
]));
assert_eq!(scanned["continued_in"], child, "{scanned}");
}
#[test]
fn a_nested_key_in_a_payload_is_never_a_lane_stamp() {
let h = Home::new();
h.write(
&format!("{ENC}/{SESSION}.jsonl"),
&format!(
"{}\n{}\n",
fg("u1", "2026-06-07T05:00:00.000Z", "hello"),
r#"{"type":"assistant","uuid":"a1","timestamp":"2026-06-07T05:00:05.000Z","message":{"role":"assistant","content":[{"type":"tool_use","id":"t1","name":"Bash","input":{"sessionKind":"bg","command":"true"}}]}}"#
),
);
let row = session_row(&h.run(&[
"list",
&format!("@{SESSION}"),
"--lineage",
"--format",
"json",
]));
assert_eq!(
row["session_kind"].as_array().map(Vec::len),
Some(0),
"a nested key is not a field: {row}"
);
}