use crate::boundary::reply::{Reply, encode};
use crate::inboxview::{Deposit, Epitaph, InboxEntry};
use crate::login::auth::AuthFailure;
use crate::steps_view::Wound;
use crate::transcript::{Block, Entry, EntryKind, Transcript, Usage};
fn entry(name: &str, raw: &str, kind: EntryKind) -> Entry {
Entry {
name: name.to_owned(),
raw: raw.as_bytes().to_vec(),
kind,
}
}
#[test]
fn every_transcript_entry_class_says_which_it_is() {
let usage: Usage = [("input_tokens".to_owned(), 5u64)].into_iter().collect();
let rows = encode(&Reply::Transcript(Transcript {
entries: vec![
entry(
"001-user.md",
"---\nfrom: user\n---\ngo\n",
EntryKind::Delivered {
sender: "user".to_owned(),
sender_name: None,
epitaph: None,
body: "go\n".to_owned(),
},
),
entry(
"002-kid.md",
"bye",
EntryKind::Delivered {
sender: "kid".to_owned(),
sender_name: None,
epitaph: Some(Epitaph::Died),
body: String::new(),
},
),
entry(
"003-opus.json",
"[]",
EntryKind::Model {
model_id: "opus".to_owned(),
blocks: vec![
Block::Thinking("hmm".to_owned()),
Block::Text("done".to_owned()),
Block::ToolUse {
id: "toolu_1".to_owned(),
name: "bash".to_owned(),
input_summary: "ls".to_owned(),
},
],
usage,
},
),
entry(
"004-tool.json",
"{}",
EntryKind::ToolResult {
tool_use_id: "toolu_1".to_owned(),
content: "a b".to_owned(),
is_error: true,
},
),
entry(
"«live»",
"half",
EntryKind::Streaming {
thinking: String::new(),
text: "half".to_owned(),
},
),
entry(
"«006–008»",
"cut",
EntryKind::Compacted {
first: 6,
last: 8,
summary: "cut".to_owned(),
},
),
entry("notes.txt", "\u{fffd}", EntryKind::Raw),
],
}));
assert_eq!(rows["kind"], "transcript");
let at = |i: usize| rows["rows"][i].clone();
assert_eq!(at(0)["kind"], "delivered");
assert_eq!(at(0)["sender"], "user");
assert_eq!(at(0)["body"], "go\n");
assert_eq!(at(0)["raw"], "---\nfrom: user\n---\ngo\n");
assert!(at(0).get("epitaph").is_none(), "not a result deposit");
assert_eq!(at(1)["epitaph"], "died");
assert_eq!(at(2)["kind"], "model");
assert_eq!(at(2)["model_id"], "opus");
assert_eq!(at(2)["usage"]["input_tokens"], 5);
assert_eq!(at(2)["blocks"][0]["kind"], "thinking");
assert_eq!(at(2)["blocks"][1]["text"], "done");
assert_eq!(at(2)["blocks"][2]["kind"], "tool-use");
assert_eq!(at(2)["blocks"][2]["input"], "ls");
assert_eq!(at(3)["kind"], "tool-result");
assert_eq!(at(3)["tool_use_id"], "toolu_1");
assert_eq!(at(3)["is_error"], true);
assert_eq!(at(4)["kind"], "streaming");
assert_eq!(at(4)["text"], "half");
assert_eq!(at(5)["kind"], "compacted");
assert_eq!(at(5)["first"], 6);
assert_eq!(at(5)["last"], 8);
assert_eq!(at(5)["summary"], "cut");
assert_eq!(at(6)["kind"], "raw");
}
#[test]
fn a_deposit_carries_what_it_stated_and_omits_what_it_did_not() {
let rows = encode(&Reply::Inbox(vec![
InboxEntry {
name: "20260814T000000Z-ab12-001.md".to_owned(),
raw: b"---\nfrom: 20260814T000000Z-ab12\nfrom_name: DulcetMongoose\n---\nhi\n".to_vec(),
deposit: Deposit {
sender: Some("20260814T000000Z-ab12".to_owned()),
from_name: Some("DulcetMongoose".to_owned()),
deposited_at: Some("2026-08-14T00:00:00Z".to_owned()),
epitaph: Some(Epitaph::FinalResponse),
terminal_ref: Some("sha".to_owned()),
body: "hi\n".to_owned(),
},
},
InboxEntry {
name: "raw-002.md".to_owned(),
raw: b"no envelope".to_vec(),
deposit: Deposit {
body: "no envelope".to_owned(),
..Deposit::default()
},
},
]));
assert_eq!(rows["kind"], "inbox");
let stated = rows["rows"][0].clone();
assert_eq!(stated["name"], "20260814T000000Z-ab12-001.md");
assert_eq!(
stated["raw"],
"---\nfrom: 20260814T000000Z-ab12\nfrom_name: DulcetMongoose\n---\nhi\n"
);
assert_eq!(stated["deposit"]["from"], "20260814T000000Z-ab12");
assert_eq!(stated["deposit"]["from_name"], "DulcetMongoose");
assert_eq!(stated["deposit"]["deposited_at"], "2026-08-14T00:00:00Z");
assert_eq!(stated["deposit"]["epitaph"], "final-response");
assert_eq!(stated["deposit"]["terminal_ref"], "sha");
assert_eq!(stated["deposit"]["body"], "hi\n");
let bare = rows["rows"][1].clone();
assert_eq!(bare["deposit"]["body"], "no envelope");
for key in [
"from",
"from_name",
"deposited_at",
"epitaph",
"terminal_ref",
] {
assert!(bare["deposit"].get(key).is_none(), "{key} was never stated");
}
}
#[test]
fn the_settled_failure_notice_says_the_wound_and_never_the_sentence() {
let rows = |wound| {
encode(&Reply::Transcript(Transcript {
entries: vec![entry(
"\u{ab}wound\u{bb}",
"banner",
EntryKind::Wounded { wound },
)],
}))["rows"][0]
.clone()
};
let refused = rows(Wound::Refused(AuthFailure::Row("acme".to_owned())));
assert_eq!(refused["kind"], "wounded");
assert_eq!(refused["wound"], "refused");
assert_eq!(refused["auth_row"], "acme");
assert!(
refused.get("wound_reason").is_none(),
"a refusal's reason is its class"
);
let unrouted = rows(Wound::Refused(AuthFailure::Unrouted));
assert_eq!(unrouted["wound"], "refused");
assert!(unrouted.get("auth_row").is_none());
let spoke = rows(Wound::Spoke("no credential".to_owned()));
assert_eq!(spoke["wound"], "no_response");
assert_eq!(spoke["wound_reason"], "no credential");
assert_eq!(rows(Wound::Mute)["wound"], "no_response");
assert_eq!(rows(Wound::OutputLimit)["wound"], "output_limit");
for row in [refused, unrouted, spoke] {
assert!(row.get("banner").is_none());
}
}