use std::path::{Path, PathBuf};
use rusqlite::Connection;
use supercode_harness::audit::{audit_dir, Corpus};
use supercode_harness::reduce::export_session_spliced;
use supercode_harness::{
ChatMessage, DiscoveryQuery, Fidelity, HarnessCatalog, HarnessHomes, HarnessId, Role, Session,
SessionFormat, SessionSource,
};
fn fixture() -> PathBuf {
Path::new(env!("CARGO_MANIFEST_DIR")).join("tests/fixtures/goose_session.json")
}
fn temp_dir(label: &str) -> PathBuf {
let path = std::env::temp_dir().join(format!(
"supercode-goose-{label}-{}-{}",
std::process::id(),
std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.as_nanos()
));
std::fs::create_dir_all(&path).unwrap();
path
}
#[test]
fn native_export_is_byte_exact_and_preserves_goose_only_blocks() {
let source = std::fs::read_to_string(fixture()).unwrap();
let session = Session::from_goose_str(&source).unwrap();
assert_eq!(session.meta.source, SessionSource::Goose);
assert_eq!(
session.meta.session_id.as_deref(),
Some("20260818_goose_fixture")
);
assert_eq!(session.meta.model.as_deref(), Some("gpt-5.6"));
assert_eq!(session.load_fidelity(), Fidelity::ByteLossless);
assert_eq!(session.messages.len(), 4);
assert_eq!(session.messages[0].role, Role::User);
assert_eq!(
session.messages[1].content.as_deref(),
Some("I will inspect it.")
);
assert_eq!(
session.messages[1].tool_calls()[0].function.name,
"developer__shell"
);
assert_eq!(
session.messages[2].tool_call_id.as_deref(),
Some("goose-call-1")
);
assert_eq!(session.to_jsonl(SessionFormat::Goose).unwrap(), source);
assert!(session
.to_native_jsonl()
.lines()
.next()
.unwrap()
.contains("\"source\":\"goose\""));
let native = session.to_native_jsonl();
let reloaded = Session::from_native_str(&native).unwrap();
assert_eq!(reloaded.to_jsonl(SessionFormat::Goose).unwrap(), source);
}
#[test]
fn appended_turns_form_a_stock_importable_goose_document_after_disk_reload() {
let source = Session::from_goose(fixture()).unwrap();
let appended = vec![
ChatMessage::user("Continue through Supercode."),
ChatMessage::assistant("Goose continuation is intact."),
];
let sidecar = source.to_native_jsonl_v2(&appended);
let dir = temp_dir("sidecar");
let sidecar_path = dir.join("session.supercode.jsonl");
std::fs::write(&sidecar_path, sidecar).unwrap();
let reloaded_sidecar = std::fs::read_to_string(&sidecar_path).unwrap();
let artifact = export_session_spliced(
&reloaded_sidecar,
SessionFormat::Goose,
Some("goose-resumed"),
)
.unwrap();
let value: serde_json::Value = serde_json::from_str(&artifact).unwrap();
assert_eq!(value["id"], "goose-resumed");
assert_eq!(value["message_count"], 6);
assert_eq!(value["conversation"][1]["content"][0]["type"], "thinking");
let reloaded = Session::from_goose_str(&artifact).unwrap();
assert_eq!(
reloaded.messages[4].content.as_deref(),
Some("Continue through Supercode.")
);
assert_eq!(
reloaded.messages[5].content.as_deref(),
Some("Goose continuation is intact.")
);
std::fs::remove_dir_all(dir).unwrap();
}
#[test]
fn sqlite_loader_reconstructs_the_official_export_boundary_read_only() {
let dir = temp_dir("sqlite");
let db = dir.join("sessions.db");
let connection = Connection::open(&db).unwrap();
connection
.execute_batch(
"
CREATE TABLE sessions (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
working_dir TEXT NOT NULL,
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL,
session_type TEXT NOT NULL,
extension_data TEXT,
goose_mode TEXT NOT NULL,
provider_name TEXT,
model_config_json TEXT,
archived_at TEXT
);
CREATE TABLE messages (
id INTEGER PRIMARY KEY AUTOINCREMENT,
message_id TEXT,
session_id TEXT NOT NULL,
role TEXT NOT NULL,
content_json TEXT NOT NULL,
created_timestamp INTEGER NOT NULL,
metadata_json TEXT
);
INSERT INTO sessions VALUES (
'sqlite-goose', 'SQLite Goose', '/tmp/goose', '2026-08-18T12:00:00Z',
'2026-08-18T12:00:01Z', 'user', '{}', 'auto', 'openai',
'{\"model_name\":\"gpt-5.6\"}', NULL
);
INSERT INTO messages (
message_id, session_id, role, content_json, created_timestamp, metadata_json
) VALUES (
'msg-1', 'sqlite-goose', 'user',
'[{\"type\":\"text\",\"text\":\"Loaded from Goose SQLite\"}]',
1787054400, '{\"userVisible\":true,\"agentVisible\":true}'
);
",
)
.unwrap();
drop(connection);
let catalog = HarnessCatalog::new();
let discovered = catalog
.discover(&DiscoveryQuery {
harnesses: vec![HarnessId::from(HarnessId::GOOSE)],
homes: HarnessHomes {
goose: db.clone(),
..HarnessHomes::default()
},
..DiscoveryQuery::default()
})
.unwrap();
assert_eq!(discovered.len(), 1);
assert_eq!(discovered[0].locator.harness.as_str(), HarnessId::GOOSE);
assert_eq!(discovered[0].message_count, Some(1));
assert_eq!(discovered[0].model.as_deref(), Some("gpt-5.6"));
let session = catalog.load(&discovered[0].locator).unwrap();
assert_eq!(session.load_fidelity(), Fidelity::ValueLossless);
assert_eq!(
session.messages[0].content.as_deref(),
Some("Loaded from Goose SQLite")
);
let exported: serde_json::Value =
serde_json::from_str(&session.to_jsonl(SessionFormat::Goose).unwrap()).unwrap();
assert_eq!(exported["id"], "sqlite-goose");
assert_eq!(exported["conversation"][0]["id"], "msg-1");
let mut follower = catalog.follow(&discovered[0].locator).unwrap();
assert!(follower.poll().unwrap().is_some());
let audit = audit_dir(&db, Corpus::Goose, Some(1));
assert_eq!(audit.files, 1);
assert_eq!(audit.lines, 1);
assert_eq!(audit.parse_errors, 0);
assert!(audit.notes.is_empty(), "{:?}", audit.notes);
std::fs::remove_dir_all(dir).unwrap();
}