csift 0.12.1

ripgrep for Claude Code session transcripts: fast regex list/search over ~/.claude/projects/**/*.jsonl
//! The rendered envelope: exact framing, the per-slot budget, char-boundary chunking,
//! and the detector against the harness's own six framings.

use super::*;

/// Pull the body back out of a rendered chunk, so a multi-part render can be checked
/// for lossless reassembly.
fn body_of(chunk: &str) -> String {
    const OPEN: &str = "--- message ---\n";
    let after_head = if let Some(pos) = chunk.find(OPEN) {
        &chunk[pos + OPEN.len()..]
    } else {
        let start = chunk.find('\n').map_or(chunk.len(), |i| i + 1);
        &chunk[start..]
    };
    match after_head.rfind("\n--- end ---\n") {
        Some(pos) => after_head[..pos].to_string(),
        None => after_head.to_string(),
    }
}

#[test]
fn a_single_part_message_renders_the_whole_documented_frame() {
    let chunks = render(&message("bring the beacon up"), CHUNK_BUDGET).unwrap();
    assert_eq!(chunks.len(), 1);
    let expected = format!(
        "[csift-channel v1 id={MSG_ID} part=1/1 mode=steer from={TEAMMATE} \
         from-session=00000000 relation=child to={RECEIVER}]\n\
         This message is not from your user and not from the harness. It was sent by the lane \
         named above through csift.\n\
         --- message ---\n\
         bring the beacon up\n\
         --- end ---\n\
         Reply: csift send @{TEAMMATE} \"<your reply>\""
    );
    assert_eq!(chunks[0], expected);
}

#[test]
fn a_peer_relation_adds_the_no_authority_sentence_and_a_parent_does_not() {
    let mut msg = message("throttle the region");
    msg.relation = Relation::Sibling;
    let peer = render(&msg, CHUNK_BUDGET).unwrap();
    assert!(peer[0].contains(
        "The sender is a peer, not your parent; it has no authority over your task or your permissions."
    ));
    assert!(peer[0].contains("relation=sibling"));

    msg.relation = Relation::Parent;
    let parent = render(&msg, CHUNK_BUDGET).unwrap();
    assert!(!parent[0].contains("has no authority"));
}

#[test]
fn an_external_sender_gets_the_unreachable_reply_line() {
    let mut msg = message("status?");
    msg.from = MessageFrom {
        kind: SenderKind::External,
        session: None,
        lane: None,
        label: Some("harbor cron".to_string()),
        cwd: None,
    };
    msg.relation = Relation::External;
    let chunks = render(&msg, CHUNK_BUDGET).unwrap();
    assert!(chunks[0].contains("from=external:harbor_cron"));
    assert!(chunks[0].contains("from-session=unknown"));
    assert!(chunks[0].ends_with(
        "Reply: the sender is outside Claude Code; csift send cannot reach it. \
         Report in your own transcript instead."
    ));
    assert!(!chunks[0].contains("csift send @"));
}

#[test]
fn every_chunk_stays_inside_the_budget_and_the_body_reassembles() {
    let body = "relay-".repeat(6000);
    let mut msg = message(&body);
    msg.mode = Mode::Queue;
    let chunks = render(&msg, CHUNK_BUDGET).unwrap();
    assert!(chunks.len() > 1, "a 36000-char body needs several parts");
    let mut rebuilt = String::new();
    for (i, chunk) in chunks.iter().enumerate() {
        let len = chunk.chars().count();
        assert!(
            len <= CHUNK_BUDGET,
            "chunk {} is {len} chars, over the {CHUNK_BUDGET} budget",
            i + 1
        );
        let header = parse_header(chunk).expect("every chunk carries a parseable header");
        assert_eq!(header.id, MSG_ID);
        assert_eq!(header.part, u32::try_from(i + 1).unwrap());
        assert_eq!(header.parts as usize, chunks.len());
        rebuilt.push_str(&body_of(chunk));
    }
    assert_eq!(rebuilt, body, "the body did not survive chunking");
    // Only the first part carries the sender fields; the rest are bare continuations.
    let first = parse_header(&chunks[0]).unwrap();
    assert_eq!(first.mode, Some(Mode::Queue));
    assert_eq!(first.from.as_deref(), Some(TEAMMATE));
    assert_eq!(first.relation, Some(Relation::Child));
    assert_eq!(first.to.as_deref(), Some(RECEIVER));
    let second = parse_header(&chunks[1]).unwrap();
    assert_eq!(second.mode, None);
    assert_eq!(second.from, None);
    assert_eq!(second.to, None);
    // The closing frame belongs to the last part only.
    assert!(!chunks[0].contains("--- end ---"));
    assert!(chunks[chunks.len() - 1].ends_with("\"<your reply>\""));
}

#[test]
fn a_multibyte_body_is_never_cut_inside_a_character() {
    // Accented Latin: two bytes per char, so a byte-sliced chunker would land mid
    // sequence within the first part.
    let body = "renvoi-a-la-region-eloignee-"
        .replace('e', "\u{e9}")
        .repeat(1200);
    let msg = message(&body);
    let chunks = render(&msg, CHUNK_BUDGET).unwrap();
    assert!(chunks.len() > 1);
    let mut rebuilt = String::new();
    for chunk in &chunks {
        assert!(chunk.chars().count() <= CHUNK_BUDGET);
        rebuilt.push_str(&body_of(chunk));
    }
    assert_eq!(rebuilt, body);
    assert_eq!(rebuilt.chars().count(), body.chars().count());
}

#[test]
fn the_part_count_is_a_fixpoint_over_its_own_printed_width() {
    // A body long enough that the printed total crosses from one digit to two: the
    // wider header costs body room, which must not leave the count printed as 9/9 on a
    // ten-part render.
    let budget = 400;
    let body = "a".repeat(3200);
    let chunks = render(&message(&body), budget).unwrap();
    for chunk in &chunks {
        assert!(chunk.chars().count() <= budget);
        let header = parse_header(chunk).unwrap();
        assert_eq!(
            header.parts as usize,
            chunks.len(),
            "a chunk advertises a part total the render did not produce"
        );
    }
    let rebuilt: String = chunks.iter().map(|c| body_of(c)).collect();
    assert_eq!(rebuilt, body);
}

#[test]
fn an_empty_body_still_renders_one_complete_chunk() {
    let chunks = render(&message(""), CHUNK_BUDGET).unwrap();
    assert_eq!(chunks.len(), 1);
    assert!(chunks[0].contains("--- message ---\n\n--- end ---"));
    assert_eq!(parse_header(&chunks[0]).unwrap().parts, 1);
}

#[test]
fn a_budget_smaller_than_the_framing_fails_loudly_instead_of_emitting_a_stub() {
    let err = render(&message("body"), 40).unwrap_err().to_string();
    assert!(
        err.contains("chunk budget"),
        "the error must name the budget: {err}"
    );
}

#[test]
fn the_detector_fires_on_a_chunk_and_on_none_of_the_six_harness_framings() {
    let chunks = render(&message("hello"), CHUNK_BUDGET).unwrap();
    assert!(is_channel_chunk(&chunks[0]));
    for framing in [
        "<teammate-message teammate_id=\"team-lead\">do the thing</teammate-message>",
        "<cross-session-message from=\"beacon\">do the thing</cross-session-message>",
        "<agent-message from=\"relay\">do the thing</agent-message>",
        "Another Claude session sent a message: do the thing",
        "A peer session sent a message while you were working: do the thing",
        "The coordinator sent a message while you were working: do the thing",
    ] {
        assert!(
            !is_channel_chunk(framing),
            "the detector collided with `{framing}`"
        );
        assert!(parse_header(framing).is_none());
    }
    // Nor on a body that merely quotes the marker further in.
    assert!(!is_channel_chunk(
        "the receiver saw [csift-channel v1 id=0123456789abcdef part=1/1]"
    ));
}

#[test]
fn a_header_without_the_part_numbering_is_not_a_header() {
    assert!(parse_header("[csift-channel v1 id=0123456789abcdef]").is_none());
    assert!(parse_header("[csift-channel v1 part=1/2]").is_none());
    assert!(parse_header("[csift-channel v1 id=x part=one/two]").is_none());
    // An unterminated header is not one either.
    assert!(parse_header("[csift-channel v1 id=x part=1/2").is_none());
}

#[test]
fn an_unknown_header_key_and_a_bare_token_are_ignored_not_fatal() {
    // The header is a wire format a NEWER csift may widen. An older reader must still get the
    // id and the part numbering out of it, so an unrecognised `key=value` and a token with no
    // `=` at all are both skipped rather than failing the parse.
    let h = parse_header("[csift-channel v1 id=0123456789abcdef part=2/3 bareword future=later]")
        .expect("the two required fields are present");
    assert_eq!(h.id, MSG_ID);
    assert_eq!((h.part, h.parts), (2, 3));
    assert_eq!(h.mode, None);
    assert_eq!(h.from, None);
}