yog 0.0.68

yog: the standalone server for litany loops — the world, the balls and the conversations, behind one wire
Documentation
//! The two inspector replies whose rows are **messages**: the conversation
//! itself and the mail waiting for it. Every entry class the parser can produce
//! has to stay distinguishable on the wire, exactly as it does on screen —
//! §15 Y12's "surface them, never drop them" in its serialized form.

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,
    }
}

/// Every `EntryKind` arm answers its own token and its own fields — a
/// delivered message, a model turn with all three block kinds and the
/// provider's own counters, a tool result, the live tail, the compaction
/// marker and the raw bucket. The eighth arm, the settled-failure notice, is
/// the beat below: it is the one whose fields are another module's vocabulary.
#[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");
    // The envelope the parsed view drops is still reachable — the headless seat
    // has no Raw toggle to reach it with.
    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");
    // The counter values cross; the sentence a seat paints from them does not
    // (bl-7bd2 — a headless seat runs the same row projection over these).
    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");
}

/// A deposit says what it stated and nothing more: a forgiving parse of a
/// hand-edited file leaves fields absent, and an absent key is a different
/// claim from an empty one.
#[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");
    // The NAME beside the id (bl-6661): the filename re-asserts the id and
    // nothing but the envelope carries this, so a seat with no live roster
    // attributed the row by sixty characters of timestamped hex.
    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");
    }
}

/// **The settled-failure notice crosses as the wound, not as the sentence**
/// (bl-015b) — the compaction marker's own ruling, read on the row that
/// carries §7.3's vocabulary instead of §5.1 #12's counters. The class, the
/// adapter's reason and the provider row cross; the banner a seat paints is a
/// projection every seat runs for itself, and it is spelled by the one encoder
/// that owns the wound, so this shape and `reply/steps` cannot drift into two
/// dialects of one enum.
#[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"
    );
    // Unrouted: refused, and no row is derivable — the honest middle, said as
    // an absent key rather than an empty string standing in for a row.
    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");
    // No sentence rides any of them: the words are the seat's projection.
    for row in [refused, unrouted, spoke] {
        assert!(row.get("banner").is_none());
    }
}