use std::path::PathBuf;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::{Arc, Mutex};
use async_trait::async_trait;
use supercode::reduce::{invert, project_messages, reduction_id, verify_log, ReductionPolicy};
use supercode::session::Session;
use supercode::sidecar::SidecarWriter;
use supercode::store::SessionStore;
use supercode::{
Agent, ChatMessage, ChatRequest, Config, FunctionCall, Provider, Role, ToolCall, Usage,
};
fn temp_dir(tag: &str) -> PathBuf {
static N: AtomicUsize = AtomicUsize::new(0);
let dir = std::env::temp_dir().join(format!(
"supercode-tr12-{tag}-{}-{}",
std::process::id(),
N.fetch_add(1, Ordering::SeqCst)
));
std::fs::create_dir_all(&dir).unwrap();
dir
}
struct BigTool(String);
#[async_trait]
impl supercode::tools::Tool for BigTool {
fn name(&self) -> &str {
"big_tool"
}
fn description(&self) -> &str {
"x"
}
fn parameters(&self) -> serde_json::Value {
serde_json::json!({"type": "object"})
}
async fn execute(
&self,
_a: serde_json::Value,
_c: &supercode::tools::ToolContext,
) -> supercode::Result<String> {
Ok(self.0.clone())
}
}
fn tool_call_msg(id: &str) -> ChatMessage {
ChatMessage {
role: Role::Assistant,
content: None,
content_parts: None,
tool_calls: Some(vec![ToolCall {
id: id.to_string(),
kind: "function".to_string(),
function: FunctionCall {
name: "big_tool".to_string(),
arguments: "{}".to_string(),
},
}]),
tool_call_id: None,
name: None,
metadata: Default::default(),
}
}
struct ToolThenPlainCapturing {
calls: AtomicUsize,
requests: Arc<Mutex<Vec<Vec<ChatMessage>>>>,
}
#[async_trait]
impl Provider for ToolThenPlainCapturing {
async fn complete(
&self,
req: &ChatRequest,
_on_delta: &(dyn for<'a> Fn(&'a str) + Send + Sync),
) -> supercode::Result<(ChatMessage, Usage)> {
let n = self.calls.fetch_add(1, Ordering::SeqCst);
self.requests.lock().unwrap().push(req.messages.clone());
if n == 0 {
Ok((tool_call_msg("c1"), Usage::default()))
} else {
Ok((
ChatMessage::assistant(format!("reply {n}")),
Usage::default(),
))
}
}
}
fn wire_bytes(msgs: &[ChatMessage]) -> usize {
serde_json::to_string(msgs).map(|s| s.len()).unwrap_or(0)
}
#[tokio::test]
async fn dev01_dev04_guarantor_regression_offline_verify_and_invert() {
let dir = temp_dir("dev01-dev04");
let store_dir = dir.join("store");
let store = SessionStore::open(&store_dir).unwrap();
let name = "tr12-dev01";
let sidecar_path = store.sidecar_path(name);
let mut original = "Q".repeat(120_000);
original.push_str("TR12-NEEDLE-DEV01");
original.push_str(&"y".repeat(150_000 - original.len()));
assert_eq!(original.len(), 150_000);
assert!(original.len() > 100_000, "must trip the default cap");
let requests = Arc::new(Mutex::new(Vec::new()));
let config = Config::builder()
.cwd(dir.clone())
.compact_after_messages(8)
.build();
let mut reg = supercode::tools::ToolRegistry::new();
reg.register(BigTool(original.clone()));
let mut agent = Agent::with_parts(
config,
Box::new(ToolThenPlainCapturing {
calls: AtomicUsize::new(0),
requests: requests.clone(),
}),
reg,
);
let empty_session = Session::from_claude_code_str("").unwrap();
let writer = SidecarWriter::create(&sidecar_path, &empty_session).unwrap();
agent.set_recorder(writer);
let policy = ReductionPolicy::default();
agent.set_reduction_policy(policy.clone());
for i in 0..6 {
let reply = agent.send(format!("turn {i}")).await.unwrap();
assert!(
reply.starts_with("reply"),
"unexpected reply at turn {i}: {reply}"
);
}
let log = agent.reduction_log().clone();
let cleared = log
.reductions
.iter()
.find_map(|r| match r.kind {
supercode::reduce::ReductionKind::TurnsCleared { first, last, .. } => {
Some((first, last))
}
_ => None,
})
.expect("a TurnsCleared reduction must have been established");
assert!(
cleared.0 <= 1 && cleared.1 >= 2,
"the big tool output must land inside the TurnsCleared range, got {cleared:?}"
);
let sidecar_raw_live = std::fs::read_to_string(&sidecar_path).unwrap();
let sidecar_live_reload = Session::from_native_str(&sidecar_raw_live).unwrap();
assert_eq!(
sidecar_live_reload.messages.len(),
agent.history().len() - 1
);
for (a, b) in sidecar_live_reload
.messages
.iter()
.zip(&agent.history()[1..])
{
assert_eq!(a.role, b.role);
assert_eq!(
a.content, b.content,
"history[1..] must equal the sidecar, byte for byte"
);
}
store.save_reduction_log(name, &log).unwrap();
let sidecar_jsonl = store
.load_sidecar(name)
.unwrap()
.expect("sidecar must exist on disk");
let sidecar = Session::from_sidecar_str(&sidecar_jsonl).unwrap();
let log_reloaded = store
.load_reduction_log(name)
.unwrap()
.expect("reduction log must exist on disk");
verify_log(&log_reloaded, &sidecar)
.expect("verify_log must pass clean against the reloaded-from-disk sidecar");
let (final_view, reprojected_log) = project_messages(&sidecar.messages, &policy, &log_reloaded);
assert_eq!(
reprojected_log, log_reloaded,
"re-projecting from the reloaded sidecar with its own log must not invent new reductions"
);
let inverted = invert(&final_view, &log_reloaded, &sidecar)
.expect("invert must pass clean against the reloaded-from-disk sidecar");
assert_eq!(inverted.len(), sidecar.messages.len());
for (a, b) in inverted.iter().zip(&sidecar.messages) {
assert_eq!(a.role, b.role);
assert_eq!(a.content, b.content);
}
let restored_tool_msg = inverted
.iter()
.find(|m| m.role == Role::Tool && m.tool_call_id.as_deref() == Some("c1"))
.and_then(|m| m.content.clone())
.expect("the big tool result must be present after invert");
assert_eq!(
restored_tool_msg, original,
"invert must restore the full 150,000-byte original byte-exact"
);
std::fs::remove_dir_all(&dir).ok();
}
#[tokio::test]
async fn dev02_gate_correctness_full_bytes_with_machinery_capped_without() {
let big = "N".repeat(150_000);
{
let dir = temp_dir("dev02-with-machinery");
let sidecar_path = dir.join("sess.sidecar.jsonl");
let config = Config::builder().cwd(dir.clone()).build();
let mut reg = supercode::tools::ToolRegistry::new();
reg.register(BigTool(big.clone()));
let requests = Arc::new(Mutex::new(Vec::new()));
let mut agent = Agent::with_parts(
config,
Box::new(ToolThenPlainCapturing {
calls: AtomicUsize::new(0),
requests,
}),
reg,
);
let empty_session = Session::from_claude_code_str("").unwrap();
let writer = SidecarWriter::create(&sidecar_path, &empty_session).unwrap();
agent.set_recorder(writer);
agent.set_reduction_policy(ReductionPolicy::default());
agent.send("go").await.unwrap();
let history_copy = agent
.history()
.iter()
.find(|m| m.role == Role::Tool)
.and_then(|m| m.content.clone())
.unwrap();
assert_eq!(
history_copy, big,
"with machinery, history must keep the FULL bytes"
);
assert!(
!history_copy.contains("bytes total, showing first"),
"with machinery, no cap notice may ever appear in history"
);
std::fs::remove_dir_all(&dir).ok();
}
{
let dir = temp_dir("dev02-legacy");
let config = Config::builder().cwd(dir.clone()).build();
let mut reg = supercode::tools::ToolRegistry::new();
reg.register(BigTool(big.clone()));
let requests = Arc::new(Mutex::new(Vec::new()));
let mut agent = Agent::with_parts(
config,
Box::new(ToolThenPlainCapturing {
calls: AtomicUsize::new(0),
requests,
}),
reg,
);
agent.send("go").await.unwrap();
let history_copy = agent
.history()
.iter()
.find(|m| m.role == Role::Tool)
.and_then(|m| m.content.clone())
.unwrap();
assert!(
history_copy.len() < big.len(),
"without machinery, legacy capping must still run"
);
assert!(
history_copy.contains("bytes total, showing first"),
"without machinery, the legacy cap notice must still appear: {history_copy}"
);
assert!(
history_copy.contains("full output not retained"),
"without a recorder, the notice must honestly say so: {history_copy}"
);
std::fs::remove_dir_all(&dir).ok();
}
}
#[tokio::test]
async fn dev03_safety_net_wire_bounded_via_a7_with_gate_off() {
let dir = temp_dir("dev03");
let sidecar_path = dir.join("sess.sidecar.jsonl");
let huge = "H".repeat(1_000_000);
assert!(huge.len() >= 100_000 * 10);
let config = Config::builder().cwd(dir.clone()).build();
let mut reg = supercode::tools::ToolRegistry::new();
reg.register(BigTool(huge.clone()));
let requests = Arc::new(Mutex::new(Vec::new()));
let mut agent = Agent::with_parts(
config,
Box::new(ToolThenPlainCapturing {
calls: AtomicUsize::new(0),
requests: requests.clone(),
}),
reg,
);
let empty_session = Session::from_claude_code_str("").unwrap();
let writer = SidecarWriter::create(&sidecar_path, &empty_session).unwrap();
agent.set_recorder(writer);
agent.set_reduction_policy(ReductionPolicy {
tool_output_keep_bytes: 4096,
tool_output_trigger_bytes: 8192,
protect_last_n_tool_results: 0,
..ReductionPolicy::default()
});
agent.send("go").await.unwrap();
let history_copy = agent
.history()
.iter()
.find(|m| m.role == Role::Tool)
.and_then(|m| m.content.clone())
.unwrap();
assert_eq!(history_copy.len(), huge.len());
let reqs = requests.lock().unwrap().clone();
let second_request = &reqs[1];
let bytes = wire_bytes(second_request);
assert!(
bytes < 50_000,
"the wire payload for the very next request must be bounded by A7, got {bytes} bytes"
);
let body = serde_json::to_string(second_request).unwrap();
assert!(
!body.contains(&huge),
"the wire payload must never contain the raw huge output"
);
assert!(
second_request.iter().any(|m| reduction_id(m).is_some()),
"the reduced view must carry a message with a reduction id"
);
std::fs::remove_dir_all(&dir).ok();
}