mod interop_common;
use std::path::{Path, PathBuf};
use interop_common::{core, measure_cell, replay_eligible, CellResidue};
use supercode::audit::{audit_dir, Corpus};
use supercode::configfile::{resolve, ResolveOptions};
use supercode::session::{Session, SessionFormat};
use supercode::ChatMessage;
fn fixture(name: &str) -> PathBuf {
Path::new(env!("CARGO_MANIFEST_DIR"))
.join("tests/fixtures")
.join(name)
}
const N: usize = 5;
const FORMATS: [SessionFormat; N] = [
SessionFormat::ClaudeCode,
SessionFormat::Codex,
SessionFormat::OpenCode,
SessionFormat::Pi,
SessionFormat::Grok,
];
fn fname(i: usize) -> &'static str {
["claude", "codex", "opencode", "pi", "grok"][i]
}
fn idx(f: SessionFormat) -> usize {
match f {
SessionFormat::ClaudeCode => 0,
SessionFormat::Codex => 1,
SessionFormat::OpenCode => 2,
SessionFormat::Pi => 3,
SessionFormat::Grok => 4,
}
}
fn fixture_file_for(f: SessionFormat) -> &'static str {
match f {
SessionFormat::ClaudeCode => "claude_code_session.jsonl",
SessionFormat::Codex => "codex_session.jsonl",
SessionFormat::OpenCode => "opencode_session.jsonl",
SessionFormat::Pi => "pi_session.jsonl",
SessionFormat::Grok => "grok_session/chat_history.jsonl",
}
}
fn load_fixture(f: SessionFormat) -> Session {
let path = fixture(fixture_file_for(f));
match f {
SessionFormat::ClaudeCode => Session::from_claude_code(path).unwrap(),
SessionFormat::Codex => Session::from_codex(path).unwrap(),
SessionFormat::OpenCode => Session::from_opencode(path).unwrap(),
SessionFormat::Pi => Session::from_pi(path).unwrap(),
SessionFormat::Grok => Session::from_grok(path).unwrap(),
}
}
fn non_empty_lines(s: &str) -> Vec<&str> {
s.lines().map(str::trim).filter(|l| !l.is_empty()).collect()
}
fn strip_native_header(native: &str) -> &str {
let idx = native
.find('\n')
.expect("native output must have a header line");
&native[idx + 1..]
}
fn keys(names: &[&str]) -> std::collections::BTreeSet<String> {
names.iter().map(|s| s.to_string()).collect()
}
const FLOOR: [[f64; N]; N] = [
[100.0, 100.0, 75.0, 75.0, 100.0],
[100.0, 100.0, 71.4, 71.4, 100.0],
[50.0, 50.0, 60.0, 60.0, 60.0],
[60.0, 60.0, 60.0, 60.0, 60.0],
[100.0, 100.0, 100.0, 100.0, 100.0],
];
fn frozen_residue(a: usize, b: usize) -> CellResidue {
let claude_cc_keys = keys(&["sourceToolAssistantUUID"]);
let codex_dropped_keys = keys(&["phase", "reasoning_encrypted"]);
let opencode_dropped_keys_to_cc = keys(&[
"agent",
"cost",
"finish",
"is_summary",
"model",
"oc_message_id",
"tokens",
]);
let opencode_dropped_keys_diag = keys(&["oc_message_id", "oc_part_id"]);
let opencode_dropped_keys_to_pi = keys(&[
"agent",
"cost",
"finish",
"is_summary",
"model",
"oc_message_id",
"oc_part_id",
"tokens",
]);
let pi_dropped_keys_cross = keys(&[
"pi_api",
"pi_bash_cancelled",
"pi_bash_command",
"pi_bash_exit_code",
"pi_bash_output",
"pi_bash_truncated",
"pi_custom_type",
"pi_details",
"pi_display",
"pi_entry_id",
"pi_first_kept_entry_id",
"pi_from_id",
"pi_msg_timestamp",
"pi_parent_id",
"pi_provider",
"pi_stop_reason",
"pi_tokens_before",
"pi_type",
"pi_usage",
]);
let pi_dropped_keys_diag = keys(&[
"pi_bash_cancelled",
"pi_bash_command",
"pi_bash_exit_code",
"pi_bash_output",
"pi_bash_truncated",
"pi_custom_type",
"pi_details",
"pi_display",
"pi_entry_id",
"pi_first_kept_entry_id",
"pi_from_id",
"pi_parent_id",
"pi_tokens_before",
"pi_type",
]);
match (a, b) {
(0, 0) => CellResidue {
compacted_out_excluded: 0,
other_dropped_messages: 0,
dropped_metadata_keys: claude_cc_keys,
},
(0, 1) => CellResidue {
compacted_out_excluded: 0,
other_dropped_messages: 0,
dropped_metadata_keys: keys(&[
"claude_uuid",
"model",
"sourceToolAssistantUUID",
"thinking",
"thinking_blocks",
"thinking_signature",
]),
},
(0, 2) | (0, 3) => CellResidue {
compacted_out_excluded: 0,
other_dropped_messages: 1,
dropped_metadata_keys: keys(&["claude_uuid", "model", "thinking_blocks"]),
},
(1, 0) | (1, 1) => CellResidue {
compacted_out_excluded: 0,
other_dropped_messages: 0,
dropped_metadata_keys: codex_dropped_keys.clone(),
},
(1, 2) | (1, 3) => CellResidue {
compacted_out_excluded: 0,
other_dropped_messages: 2,
dropped_metadata_keys: codex_dropped_keys,
},
(2, 0) | (2, 1) => CellResidue {
compacted_out_excluded: 4,
other_dropped_messages: 1,
dropped_metadata_keys: opencode_dropped_keys_to_cc,
},
(2, 2) => CellResidue {
compacted_out_excluded: 4,
other_dropped_messages: 0,
dropped_metadata_keys: opencode_dropped_keys_diag,
},
(2, 3) => CellResidue {
compacted_out_excluded: 4,
other_dropped_messages: 0,
dropped_metadata_keys: opencode_dropped_keys_to_pi,
},
(3, 0) | (3, 1) | (3, 2) => CellResidue {
compacted_out_excluded: 4,
other_dropped_messages: 0,
dropped_metadata_keys: pi_dropped_keys_cross,
},
(3, 3) => CellResidue {
compacted_out_excluded: 4,
other_dropped_messages: 0,
dropped_metadata_keys: pi_dropped_keys_diag,
},
(0, 4) | (1, 4) | (4, 0) | (4, 1) | (4, 2) | (4, 3) | (4, 4) => CellResidue {
compacted_out_excluded: 0,
other_dropped_messages: 0,
dropped_metadata_keys: keys(&[]),
},
(2, 4) | (3, 4) => CellResidue {
compacted_out_excluded: 4,
other_dropped_messages: 0,
dropped_metadata_keys: keys(&[]),
},
_ => unreachable!("all 25 cells covered above"),
}
}
#[test]
fn fidelity_matrix_5x5_and_residue() {
let sessions: Vec<Session> = FORMATS.iter().map(|&f| load_fixture(f)).collect();
println!("\n=== §4.1 TRANSLATION FIDELITY MATRIX (5x5, msg_eq_multimodal) ===");
let mut header = format!("{:<10}", "from\\to");
for i in 0..N {
header.push_str(&format!("{:>16}", fname(i)));
}
println!("{header}");
let mut cells: Vec<Vec<(f64, usize, CellResidue)>> = Vec::with_capacity(N);
for (ai, a) in FORMATS.iter().enumerate() {
let s1 = &sessions[ai];
let m1 = core(&s1.messages);
let mut row = Vec::with_capacity(N);
let mut line = format!("{:<10}", fname(ai));
for b in FORMATS.iter() {
let exported = s1
.to_jsonl(*b)
.unwrap_or_else(|e| panic!("{a:?}->{b:?}: to_jsonl failed: {e}"));
let s2 = Session::load_str(&exported, *b)
.unwrap_or_else(|e| panic!("{a:?}->{b:?}: reload failed: {e}"));
let m2 = core(&s2.messages);
let metric = measure_cell(&m1, &m2);
line.push_str(&format!(
"{:>10.1}%(r{})",
metric.pct(),
metric.residue.count()
));
row.push((metric.pct(), metric.residue.count(), metric.residue));
}
println!("{line}");
cells.push(row);
}
println!("\n=== residue detail per cell (measured, S7) ===");
for (ai, _a) in FORMATS.iter().enumerate() {
for (bi, _b) in FORMATS.iter().enumerate() {
let (pct, count, residue) = &cells[ai][bi];
println!(
" {} -> {}: {:.1}% lossless, residue={} \
(compacted_out_excluded={}, other_dropped_messages={}, dropped_metadata_keys={:?})",
fname(ai),
fname(bi),
pct,
count,
residue.compacted_out_excluded,
residue.other_dropped_messages,
residue.dropped_metadata_keys
);
}
}
for ai in 0..N {
for bi in 0..N {
let (pct, _count, residue) = &cells[ai][bi];
assert!(
*pct >= FLOOR[ai][bi] - 1e-9,
"{} -> {}: {:.2}% lossless is below the frozen floor {:.2}%",
fname(ai),
fname(bi),
pct,
FLOOR[ai][bi]
);
assert_eq!(
*residue,
frozen_residue(ai, bi),
"{} -> {}: measured residue drifted from the frozen table",
fname(ai),
fname(bi)
);
}
}
}
#[test]
fn diagonal_native_round_trip_is_the_real_100_percent() {
for &f in &FORMATS {
let s1 = load_fixture(f);
let original = std::fs::read_to_string(fixture(fixture_file_for(f))).unwrap();
let native = s1.to_native_jsonl();
let body = strip_native_header(&native);
match f {
SessionFormat::ClaudeCode
| SessionFormat::Codex
| SessionFormat::Pi
| SessionFormat::Grok => {
assert_eq!(
body, original,
"{f:?}: T1-byte native round-trip must reproduce the ORIGINAL fixture bytes"
);
println!(
" native[{}]: T1-byte byte-equal ({} bytes) — PASS (the real \"100%\")",
fname(idx(f)),
original.len()
);
}
SessionFormat::OpenCode => {
let a_lines = non_empty_lines(&original);
let b_lines = non_empty_lines(body);
assert_eq!(
a_lines.len(),
b_lines.len(),
"opencode: T1-value envelope count must survive"
);
for (i, (x, y)) in a_lines.iter().zip(&b_lines).enumerate() {
let va: serde_json::Value = serde_json::from_str(x)
.unwrap_or_else(|e| panic!("original envelope {i} invalid: {e}"));
let vb: serde_json::Value = serde_json::from_str(y)
.unwrap_or_else(|e| panic!("reconstructed envelope {i} invalid: {e}"));
assert_eq!(
va, vb,
"opencode: T1-value envelope {i} must be parsed-JSON-equal"
);
}
println!(
" native[opencode]: T1-value parsed-JSON-equal ({} envelopes) — PASS \
(the real \"100%\")",
a_lines.len()
);
}
}
let reloaded = Session::from_native_str(&native).unwrap();
assert_eq!(
s1.raw.len(),
reloaded.raw.len(),
"{f:?}: native round-trip raw line count must survive"
);
}
}
fn known_defect_count_delta(_source: SessionFormat, _target: SessionFormat) -> i64 {
0
}
#[test]
fn compacted_session_cell_exported_context_length_matches_replay_slice() {
for &source in &[SessionFormat::Pi, SessionFormat::OpenCode] {
let s1 = load_fixture(source);
let replay_slice = replay_eligible(&core(&s1.messages));
assert!(
replay_slice.len() < core(&s1.messages).len(),
"sanity: the {source:?} fixture must actually have compacted-out history \
(else this assertion is vacuous)"
);
for &target in &FORMATS {
let exported = s1.to_jsonl(target).unwrap();
let s2 = Session::load_str(&exported, target).unwrap();
let exported_context = core(&s2.messages);
let delta = known_defect_count_delta(source, target);
let expected_len = (replay_slice.len() as i64 + delta) as usize;
assert_eq!(
exported_context.len(),
expected_len,
"{source:?} -> {target:?}: exported context length ({}) must equal the source \
harness's OWN replay slice ({}) — not the full linearization (double-inclusion \
would inflate this; a nonzero delta here would mean a known defect reappeared)",
exported_context.len(),
replay_slice.len()
);
if delta != 0 {
println!(
" {source:?} -> {target:?}: context length {} (replay slice {} {delta:+}) \
— UNEXPECTED drift from 0 (see this test's module-level doc comment)",
exported_context.len(),
replay_slice.len(),
);
}
}
println!(
"compacted-session cell: {source:?}'s replay slice ({} messages) reproduced \
(no double-inclusion) across all {N} export targets — PASS",
replay_slice.len()
);
}
}
#[test]
fn a_to_b_to_a_round_trip_identity() {
println!("\n=== §4.1 A->B->A round-trip identity ===");
let mut failures: Vec<String> = Vec::new();
for &a in &FORMATS {
let s1 = load_fixture(a);
for &b in &FORMATS {
let exported_b = s1.to_jsonl(b).unwrap();
let s2 = Session::load_str(&exported_b, b).unwrap();
let exported_a = s2.to_jsonl(a).unwrap();
let s3 = Session::load_str(&exported_a, a).unwrap();
let expected = replay_eligible(&core(&s1.messages));
let got = core(&s3.messages);
let leg1 = measure_cell(&core(&s1.messages), &core(&s2.messages));
let leg2 = measure_cell(&core(&s2.messages), &got);
let delta = known_defect_count_delta(a, b);
if delta == 0 {
let ok = expected.len() == got.len()
&& expected
.iter()
.zip(&got)
.all(|(x, y)| interop_common::msg_eq_multimodal(x, y));
println!(
" {} -> {} -> {}: {} (leg1 residue={}, leg2 residue={})",
fname(idx(a)),
fname(idx(b)),
fname(idx(a)),
if ok { "PASS" } else { "FAIL" },
leg1.residue.count(),
leg2.residue.count(),
);
if !ok {
failures.push(format!(
"{a:?}->{b:?}->{a:?}: identity broken (expected {} messages, got {}); \
this pair has NO pinned known-defect delta — this would be a NEW \
regression",
expected.len(),
got.len()
));
}
} else {
let expected_len = (expected.len() as i64 + delta) as usize;
let pin_metric = measure_cell(&expected, &got);
let pinned_ok = got.len() == expected_len
&& pin_metric.residue.compacted_out_excluded == 0
&& pin_metric.residue.other_dropped_messages == delta.unsigned_abs() as usize;
println!(
" {} -> {} -> {}: PINNED KNOWN DEFECT (delta={delta:+}) — {} matched / {} \
expected, got {} messages, unmatched={} — {}",
fname(idx(a)),
fname(idx(b)),
fname(idx(a)),
pin_metric.matched,
expected.len(),
got.len(),
pin_metric.residue.other_dropped_messages,
if pinned_ok {
"PINNED (see module doc comment)"
} else {
"DRIFTED"
},
);
if !pinned_ok {
failures.push(format!(
"{a:?}->{b:?}->{a:?}: KNOWN-DEFECT pin drifted — expected len \
{expected_len} (delta {delta:+}), got len {} with {} unmatched \
(expected exactly {})",
got.len(),
pin_metric.residue.other_dropped_messages,
delta.unsigned_abs()
));
}
}
}
}
assert!(
failures.is_empty(),
"A->B->A round-trip identity failures:\n {}",
failures.join("\n ")
);
}
#[test]
fn completeness_guard_no_unknown_discriminants_for_pi_or_opencode() {
for (file, corpus) in [
("pi_session.jsonl", Corpus::Pi),
("opencode_session.jsonl", Corpus::OpenCode),
] {
let tmp = std::env::temp_dir().join(format!(
"sc-matrix-cov-{}-{}",
std::process::id(),
file.replace('.', "_")
));
std::fs::create_dir_all(&tmp).unwrap();
std::fs::copy(fixture(file), tmp.join(file)).unwrap();
let report = audit_dir(&tmp, corpus, None);
assert_eq!(report.parse_errors, 0, "{corpus:?}: typed parse errors");
let unknown: Vec<_> = report
.records
.keys()
.filter(|k| {
k.starts_with("<line>/")
|| k.contains("UnknownRole")
|| k.contains("UnknownType")
|| k.contains("UnknownStatus")
|| k.contains("UnknownImageShape")
})
.collect();
assert!(
unknown.is_empty(),
"{corpus:?}: unknown/unmodeled discriminants: {unknown:?}"
);
std::fs::remove_dir_all(&tmp).ok();
}
println!("completeness guard: no Unknown discriminant bucket for pi or opencode — PASS");
}
#[test]
fn fixture_floor_pi_and_opencode_are_multimodal() {
let pi = load_fixture(SessionFormat::Pi);
assert!(
pi.messages.iter().any(|m| m.content_parts.is_some()),
"pi fixture must contain >=1 multimodal message"
);
let oc = load_fixture(SessionFormat::OpenCode);
assert!(
oc.messages.iter().any(|m| m.content_parts.is_some()),
"opencode fixture must contain >=1 multimodal message"
);
println!("fixture floor: pi + opencode fixtures both carry >=1 multimodal message — PASS");
}
#[test]
fn claude_standalone_thinking_emits_native_opencode_reasoning_time() {
let claude = load_fixture(SessionFormat::ClaudeCode);
let exported = claude.to_jsonl(SessionFormat::OpenCode).unwrap();
let doc: serde_json::Value = serde_json::from_str(&exported).unwrap();
let reasoning = doc["messages"]
.as_array()
.unwrap()
.iter()
.flat_map(|message| message["parts"].as_array().unwrap())
.find(|part| part["type"] == "reasoning")
.expect("Claude thinking-only turn must emit an OpenCode reasoning part");
let start = reasoning["time"]["start"]
.as_i64()
.expect("OpenCode reasoning.time.start must be an integer unix-ms timestamp");
let end = reasoning["time"]["end"]
.as_i64()
.expect("OpenCode reasoning.time.end must be an integer unix-ms timestamp");
assert_eq!(start, end, "synthesized reasoning is a zero-duration span");
}
const PRESET_BEHAVIORAL_VECTORS: [(&str, SessionFormat, &str); 4] = [
(
"pi-core",
SessionFormat::Pi,
"pi_real_corpus_tool_call.jsonl",
),
(
"cc-parity",
SessionFormat::ClaudeCode,
"claude_code_session.jsonl",
),
(
"cx-parity",
SessionFormat::Codex,
"codex_real_rollout_tools.jsonl",
),
(
"oc-parity",
SessionFormat::OpenCode,
"opencode_session.jsonl",
),
];
fn load_by_format(format: SessionFormat, file: &str) -> Session {
let path = fixture(file);
match format {
SessionFormat::ClaudeCode => Session::from_claude_code(path).unwrap(),
SessionFormat::Codex => Session::from_codex(path).unwrap(),
SessionFormat::OpenCode => Session::from_opencode(path).unwrap(),
SessionFormat::Pi => Session::from_pi(path).unwrap(),
SessionFormat::Grok => Session::from_grok(path).unwrap(),
}
}
#[test]
fn preset_behavioral_vectors_corpus_based_stock_resume_acceptance() {
for (preset, format, file) in PRESET_BEHAVIORAL_VECTORS {
let resolved = resolve(
&format!("extends = \"{preset}\"\n"),
None,
&ResolveOptions::default(),
)
.unwrap_or_else(|e| panic!("preset `{preset}` failed to resolve: {e}"));
assert!(
!resolved.modules.is_empty(),
"preset `{preset}` resolved with an empty module activation set — the resolver \
regressed to a no-op"
);
let original = load_by_format(format, file);
let original_len = original.messages.len();
assert!(
original_len > 0,
"{preset} ({format:?}): fixture {file} must have >=1 message to prove anything"
);
let appended = vec![
ChatMessage::user(format!(
"{preset} behavioral-vector synthetic continuation turn"
)),
ChatMessage::assistant(format!(
"{preset} behavioral-vector synthetic continuation reply"
)),
];
let sidecar = original.to_native_jsonl_v2(&appended);
let reconstructed = Session::from_sidecar_str(&sidecar).unwrap_or_else(|e| {
panic!("{preset} ({format:?}): native-v2 sidecar failed to reload: {e}")
});
let out = reconstructed
.to_jsonl_spliced(format, None)
.unwrap_or_else(|e| panic!("{preset} ({format:?}): to_jsonl_spliced failed: {e}"));
let reloaded = Session::load_str(&out, format).unwrap_or_else(|e| {
panic!(
"{preset} ({format:?}): spliced output failed to reload with its own loader: {e}"
)
});
assert!(
reloaded.messages.len() > original_len,
"{preset} ({format:?}): spliced session must carry MORE messages than the imported \
prefix alone (imported {original_len}, reloaded {})",
reloaded.messages.len()
);
let has_user_turn = reloaded.messages.iter().any(|m| {
m.content
.as_deref()
.is_some_and(|c| c.contains("behavioral-vector synthetic continuation turn"))
});
let has_assistant_turn = reloaded.messages.iter().any(|m| {
m.content
.as_deref()
.is_some_and(|c| c.contains("behavioral-vector synthetic continuation reply"))
});
assert!(
has_user_turn && has_assistant_turn,
"{preset} ({format:?}): the appended continuation turn must survive the \
preset-targeted format's own splice+reload round trip"
);
}
println!(
"preset behavioral vectors: {} presets, all resolved + corpus-based stock-resume \
acceptance passed. NOTE: independent stock-CLI acceptance is exercised by \
scripts/stock-resume-matrix-probe.mjs for claude/codex/opencode/pi/grok and \
recorded in its content-free dated receipt.",
PRESET_BEHAVIORAL_VECTORS.len()
);
}