liminal-cli 0.3.4

The liminal command: serve the network, maintain its stores, or serve its discovery MCP over stdio
Documentation
//! These tests require the local real-exchange fixture described by the proof.
//! They never substitute a worker or a mock exchange for the production server.

#[path = "agent_fake/lab.rs"]
mod lab;
use lab::{Event, Lab};

fn present(lab: &mut Lab) -> anyhow::Result<()> {
    lab.watch("presence")?;
    lab.until(|event| matches!(event, Event::Network(subject, value) if subject.rsplit('.').next() == Some("presence") && value["present"] == true))?;
    Ok(())
}

#[test]
fn offers_two_accepts_one_and_streams_only_permitted_text() -> anyhow::Result<()> {
    let mut lab = Lab::new("stream-one", &["--version", "1"])?;
    present(&mut lab)?;
    lab.watch("stream")?;
    lab.send("inbox", "synthetic input")?;
    let event =
        lab.until(|event| matches!(event, Event::Control(value) if value["event"] == "prompt"))?;
    if let Event::Control(value) = event {
        assert_eq!(value["text"], "synthetic input");
    }
    let event = lab.until(|event| matches!(event, Event::Network(subject, value) if subject.rsplit('.').next() == Some("stream") && value["type"] == "tool_call"))?;
    if let Event::Network(_, value) = event {
        assert_eq!(value["title"], "Synthetic review");
        let encoded = serde_json::to_string(&value)?;
        for forbidden in ["rawInput", "rawOutput", "private", "file contents"] {
            assert!(!encoded.contains(forbidden));
        }
    }
    lab.terminate()?;
    assert_eq!(lab.finish(143)?, 1);
    Ok(())
}

#[test]
fn v2_prompt_ack_does_not_release_mail_until_idle() -> anyhow::Result<()> {
    let mut lab = Lab::new("stream-two", &["--version", "2", "--hold"])?;
    present(&mut lab)?;
    lab.watch("stream")?;
    lab.send("inbox", "first")?;
    lab.until(|event| matches!(event, Event::Control(value) if value["event"] == "prompt" && value["turn"] == 1))?;
    lab.until(|event| matches!(event, Event::Network(subject, value) if subject.rsplit('.').next() == Some("stream") && value["type"] == "prompt_accepted"))?;
    lab.send("inbox", "second")?;
    lab.until(|event| matches!(event, Event::Network(subject, value) if subject.rsplit('.').next() == Some("stream") && value["type"] == "prompt_queued"))?;
    lab.command("finish")?;
    lab.until(|event| matches!(event, Event::Control(value) if value["event"] == "turn_ended" && value["turn"] == 1))?;
    lab.until(|event| matches!(event, Event::Control(value) if value["event"] == "prompt" && value["turn"] == 2))?;
    lab.terminate()?;
    assert_eq!(lab.finish(143)?, 1);
    Ok(())
}

#[test]
fn version_three_is_refused_before_a_session_and_revoked() -> anyhow::Result<()> {
    let lab = Lab::new("version-three", &["--version", "3"])?;
    assert_eq!(lab.finish(1)?, 1);
    Ok(())
}

#[test]
fn thirty_third_unread_prompt_is_refused_and_cancel_reaches_the_peer() -> anyhow::Result<()> {
    let mut lab = Lab::new("queue", &["--hold"])?;
    present(&mut lab)?;
    lab.watch("stream")?;
    lab.send("inbox", "active")?;
    lab.until(|event| matches!(event, Event::Control(value) if value["event"] == "prompt"))?;
    for n in 0..33 {
        lab.send("inbox", &format!("mail {n}"))?;
    }
    lab.until(|event| matches!(event, Event::Network(subject, value) if subject.rsplit('.').next() == Some("stream") && value["type"] == "host_refusal" && value["reason"] == "prompt_queue 32 reached: 32 unread prompts"))?;
    lab.send("cancel", "cancel the active turn")?;
    lab.until(|event| matches!(event, Event::Control(value) if value["event"] == "cancel"))?;
    lab.terminate()?;
    assert_eq!(lab.finish(143)?, 1);
    Ok(())
}

fn permission(scenario: &str, count: usize, decision: &str, selected: &str) -> anyhow::Result<()> {
    let count_text = count.to_string();
    let mut lab = Lab::new(scenario, &["--burst", &count_text])?;
    present(&mut lab)?;
    lab.watch("state")?;
    lab.send("inbox", "synthetic permission turn")?;
    let waiting = lab.until(|event| matches!(event, Event::Network(subject, value) if subject.rsplit('.').next() == Some("state") && value["state"] == "waiting" && value["count"] == count))?;
    if let Event::Network(_, value) = waiting {
        assert!(
            value["words"]
                .as_str()
                .is_some_and(|words| words.contains("Synthetic review"))
        );
    }
    lab.decide_and_pull(decision, count)?;
    let answered = lab.until(|event| matches!(event, Event::Control(value) if value["event"] == "permission_answer" && value["count"] == count))?;
    if let Event::Control(value) = answered {
        assert_eq!(value["outcome"]["optionId"], selected);
    }
    lab.terminate()?;
    assert_eq!(lab.finish(143)?, 1);
    Ok(())
}

#[test]
fn an_approved_draft_selects_the_narrow_option() -> anyhow::Result<()> {
    permission("approve", 1, "approved", "yes")
}

#[test]
fn a_refused_draft_selects_the_narrow_refusal() -> anyhow::Result<()> {
    permission("refuse", 1, "refused", "no")
}

#[test]
fn seven_hundred_twenty_nine_drafts_are_answered_without_a_pipe_stall() -> anyhow::Result<()> {
    permission("burst", 729, "approved", "yes")
}

fn exits(scenario: &str, args: &[&str], state: &str) -> anyhow::Result<()> {
    let mut lab = Lab::new(scenario, args)?;
    present(&mut lab)?;
    lab.watch("presence")?;
    lab.watch("state")?;
    lab.expect_exit(3);
    lab.send("inbox", "exit fixture")?;
    lab.until(|event| matches!(event, Event::Network(subject, value) if subject.rsplit('.').next() == Some("presence") && value["present"] == false && value["exit_status"] == 3))?;
    lab.until(|event| matches!(event, Event::Network(subject, value) if subject.rsplit('.').next() == Some("state") && value["session_state"] == state))?;
    assert_eq!(lab.finish(3)?, 1);
    Ok(())
}

#[test]
fn exit_three_is_gone_and_resumable_only_when_advertised() -> anyhow::Result<()> {
    exits("exit-load", &["--exit", "3"], "dormant")
}

#[test]
fn exit_three_without_load_session_is_ended() -> anyhow::Result<()> {
    exits("exit-no-load", &["--exit", "3", "--no-load"], "ended")
}

#[test]
fn sigterm_revokes_once_and_closes_presence() -> anyhow::Result<()> {
    let mut lab = Lab::new("sigterm", &[])?;
    present(&mut lab)?;
    lab.terminate()?;
    assert_eq!(lab.finish(143)?, 1);
    Ok(())
}

fn streamed(lab: &mut Lab, kind: &str) -> anyhow::Result<serde_json::Value> {
    match lab.until(|event| matches!(event, Event::Network(subject, value) if subject.rsplit('.').next() == Some("stream") && value["type"] == kind))? {
        Event::Network(_, value) => Ok(value),
        _ => anyhow::bail!("no {kind} on the stream"),
    }
}

#[test]
fn a_config_change_reaches_the_harness_and_a_refused_one_is_said() -> anyhow::Result<()> {
    let mut lab = Lab::new("config", &["--version", "1"])?;
    present(&mut lab)?;
    lab.watch("stream")?;
    lab.send_value(
        "inbox",
        &serde_json::json!({"config":{"option":"model","value":"fake-large"}}),
    )?;
    lab.until(|event| matches!(event, Event::Control(value) if value["event"] == "config_set" && value["value"] == "fake-large"))?;
    let options = streamed(&mut lab, "config_options")?;
    assert_eq!(
        options["options"][0]["currentValue"], "fake-large",
        "{options}"
    );
    lab.send_value(
        "inbox",
        &serde_json::json!({"config":{"option":"model","value":"fake-none"}}),
    )?;
    let failed = streamed(&mut lab, "config_failed")?;
    assert_eq!(failed["code"], -32602, "{failed}");
    lab.terminate()?;
    assert_eq!(lab.finish(143)?, 1);
    Ok(())
}

#[test]
fn the_harness_session_list_is_streamed_newest_first() -> anyhow::Result<()> {
    let mut lab = Lab::new("sessions", &["--version", "1"])?;
    present(&mut lab)?;
    lab.watch("stream")?;
    lab.send_value("inbox", &serde_json::json!({"session":{"list":true}}))?;
    lab.until(|event| matches!(event, Event::Control(value) if value["event"] == "session_list"))?;
    let listed = streamed(&mut lab, "sessions")?;
    assert_eq!(listed["current"], "fake-session", "{listed}");
    assert_eq!(listed["sessions"][0]["id"], "fake-session", "{listed}");
    assert_eq!(listed["sessions"][1]["id"], "fake-earlier", "{listed}");
    lab.terminate()?;
    assert_eq!(lab.finish(143)?, 1);
    Ok(())
}