use std::path::PathBuf;
use supercode_harness::audit::{audit_dir, Corpus};
#[test]
fn claude_frame_link_is_typed_and_audited_as_named_dropped_metadata() {
let tmp = std::env::temp_dir().join(format!("sc-cov-claude-frame-link-{}", std::process::id()));
std::fs::create_dir_all(&tmp).unwrap();
let jsonl = r#"{"type":"frame-link","sessionId":"s","path":"artifact.html","frameUrl":"https://claude.ai/frame/example","timestamp":"2026-07-12T00:00:00Z"}
"#;
std::fs::write(tmp.join("session.jsonl"), jsonl).unwrap();
let report = audit_dir(&tmp, Corpus::ClaudeCode, None);
assert_eq!(report.parse_errors, 0);
let (coverage, tally) = report
.records
.get("frame-link")
.expect("frame-link must be a named typed record, not <line>/frame-link");
assert_eq!(*coverage, supercode_harness::audit::Coverage::Dropped);
assert_eq!(tally.count, 1);
for field in ["sessionId", "path", "frameUrl", "timestamp"] {
assert_eq!(
tally.unmodeled_fields.get(field),
Some(&1),
"the named Dropped residue must enumerate frame-link field `{field}`"
);
}
assert!(!report.records.contains_key("<line>/frame-link"));
std::fs::remove_dir_all(&tmp).ok();
}
#[test]
fn claude_file_history_delta_is_a_named_typed_record_not_unknown() {
let tmp = std::env::temp_dir().join(format!("sc-cov-claude-fh-delta-{}", std::process::id()));
std::fs::create_dir_all(&tmp).unwrap();
let jsonl = r#"{"type":"file-history-delta","messageId":"ba614ba8-6fcc-4138-ac56-3d579ea35f05","snapshotMessageId":"16f1900f-97ad-462e-abe0-fba9d376acfd","trackingPath":"SERIES.md","backup":{"backupFileName":null,"version":1,"backupTime":"2026-07-31T18:59:13.747Z","realParentDir":"/tmp/work"},"timestamp":"2026-07-31T18:59:13.756Z"}
"#;
std::fs::write(tmp.join("session.jsonl"), jsonl).unwrap();
let report = audit_dir(&tmp, Corpus::ClaudeCode, None);
assert_eq!(report.parse_errors, 0);
assert!(
!report.records.contains_key("<line>/file-history-delta"),
"file-history-delta must be a named typed record, not an Unknown-bucket line"
);
let (_coverage, tally) = report
.records
.get("file-history-delta")
.expect("file-history-delta must be a named typed record");
assert_eq!(tally.count, 1);
std::fs::remove_dir_all(&tmp).ok();
}
#[test]
fn files_api_image_block_is_audited_as_dropped_not_normalized() {
let tmp =
std::env::temp_dir().join(format!("sc-cov-d5-files-api-image-{}", std::process::id()));
std::fs::create_dir_all(&tmp).unwrap();
let jsonl = r#"{"type":"user","message":{"role":"user","content":[{"type":"image","source":{"type":"file","file_id":"file_abc123"}}]},"sessionId":"s"}
"#;
std::fs::write(tmp.join("session.jsonl"), jsonl).unwrap();
let report = audit_dir(&tmp, Corpus::ClaudeCode, None);
let count = report
.blocks
.get(&(
"image".to_string(),
supercode_harness::audit::Coverage::Dropped,
))
.copied()
.expect("the `image` block discriminant must be tallied under Dropped");
assert_eq!(count, 1);
assert!(
!report.blocks.contains_key(&(
"image".to_string(),
supercode_harness::audit::Coverage::Normalized
)),
"an unconvertible (Files-API) image source must be audited as Dropped, not Normalized"
);
std::fs::remove_dir_all(&tmp).ok();
}
#[test]
fn base64_image_block_is_still_audited_as_normalized() {
let tmp = std::env::temp_dir().join(format!("sc-cov-d5-base64-image-{}", std::process::id()));
std::fs::create_dir_all(&tmp).unwrap();
let jsonl = r#"{"type":"user","message":{"role":"user","content":[{"type":"image","source":{"type":"base64","media_type":"image/png","data":"aGVsbG8="}}]},"sessionId":"s"}
"#;
std::fs::write(tmp.join("session.jsonl"), jsonl).unwrap();
let report = audit_dir(&tmp, Corpus::ClaudeCode, None);
let count = report
.blocks
.get(&(
"image".to_string(),
supercode_harness::audit::Coverage::Normalized,
))
.copied()
.expect("the `image` block discriminant must be tallied under Normalized");
assert_eq!(count, 1);
assert!(!report.blocks.contains_key(&(
"image".to_string(),
supercode_harness::audit::Coverage::Dropped
)));
std::fs::remove_dir_all(&tmp).ok();
}
#[test]
fn empty_base64_image_block_is_audited_as_dropped_not_normalized() {
let tmp = std::env::temp_dir().join(format!(
"sc-cov-n3-empty-base64-image-{}",
std::process::id()
));
std::fs::create_dir_all(&tmp).unwrap();
let jsonl = r#"{"type":"user","message":{"role":"user","content":[{"type":"image","source":{"type":"base64","data":""}}]},"sessionId":"s"}
"#;
std::fs::write(tmp.join("session.jsonl"), jsonl).unwrap();
let report = audit_dir(&tmp, Corpus::ClaudeCode, None);
let count = report
.blocks
.get(&(
"image".to_string(),
supercode_harness::audit::Coverage::Dropped,
))
.copied()
.expect("the `image` block discriminant must be tallied under Dropped");
assert_eq!(count, 1);
assert!(
!report.blocks.contains_key(&(
"image".to_string(),
supercode_harness::audit::Coverage::Normalized
)),
"an empty base64 image source must be audited as Dropped, not Normalized, \
matching the loader's own unconvertible treatment"
);
std::fs::remove_dir_all(&tmp).ok();
}
#[test]
fn mixed_corpus_image_coverage_is_not_collapsed_by_last_write() {
let tmp = std::env::temp_dir().join(format!(
"sc-cov-n1-mixed-corpus-image-{}",
std::process::id()
));
std::fs::create_dir_all(&tmp).unwrap();
let a = r#"{"type":"user","message":{"role":"user","content":[{"type":"image","source":{"type":"file","file_id":"file_abc123"}}]},"sessionId":"s"}
"#;
let b = r#"{"type":"user","message":{"role":"user","content":[{"type":"image","source":{"type":"base64","media_type":"image/png","data":"aGVsbG8="}}]},"sessionId":"s"}
"#;
std::fs::write(tmp.join("a.jsonl"), a).unwrap();
std::fs::write(tmp.join("b.jsonl"), b).unwrap();
let report = audit_dir(&tmp, Corpus::ClaudeCode, None);
let dropped = report
.blocks
.get(&(
"image".to_string(),
supercode_harness::audit::Coverage::Dropped,
))
.copied()
.unwrap_or(0);
let normalized = report
.blocks
.get(&(
"image".to_string(),
supercode_harness::audit::Coverage::Normalized,
))
.copied()
.unwrap_or(0);
assert_eq!(
dropped, 1,
"the Files-API image instance must be counted as Dropped, not collapsed away \
(got dropped={dropped}, normalized={normalized})"
);
assert_eq!(
normalized, 1,
"the base64 image instance must independently be counted as Normalized \
(got dropped={dropped}, normalized={normalized})"
);
std::fs::remove_dir_all(&tmp).ok();
}
#[test]
fn nested_tool_result_image_is_audited_as_normalized() {
let tmp = std::env::temp_dir().join(format!(
"sc-cov-parity11-nested-image-normalized-{}",
std::process::id()
));
std::fs::create_dir_all(&tmp).unwrap();
let jsonl = r#"
{"type":"assistant","message":{"role":"assistant","content":[{"type":"tool_use","id":"t1","name":"Read","input":{}}]},"sessionId":"s"}
{"type":"user","message":{"role":"user","content":[{"type":"tool_result","tool_use_id":"t1","content":[{"type":"text","text":"screenshot"},{"type":"image","source":{"type":"base64","media_type":"image/png","data":"aGVsbG8="}}]}]},"sessionId":"s"}
"#;
std::fs::write(tmp.join("session.jsonl"), jsonl).unwrap();
let report = audit_dir(&tmp, Corpus::ClaudeCode, None);
let normalized = report
.blocks
.get(&(
"tool_result/image".to_string(),
supercode_harness::audit::Coverage::Normalized,
))
.copied()
.expect("a well-formed nested image must be tallied under tool_result/image: Normalized");
assert_eq!(normalized, 1);
assert!(
!report.blocks.contains_key(&(
"tool_result/image".to_string(),
supercode_harness::audit::Coverage::Dropped
)),
"a well-formed base64 nested image must not also show up as Dropped"
);
assert!(report.blocks.contains_key(&(
"tool_result".to_string(),
supercode_harness::audit::Coverage::Normalized
)));
std::fs::remove_dir_all(&tmp).ok();
}
#[test]
fn nested_tool_result_image_unconvertible_source_is_audited_as_dropped() {
let tmp = std::env::temp_dir().join(format!(
"sc-cov-parity11-nested-image-dropped-{}",
std::process::id()
));
std::fs::create_dir_all(&tmp).unwrap();
let jsonl = r#"
{"type":"assistant","message":{"role":"assistant","content":[{"type":"tool_use","id":"t1","name":"Read","input":{}}]},"sessionId":"s"}
{"type":"user","message":{"role":"user","content":[{"type":"tool_result","tool_use_id":"t1","content":[{"type":"image","source":{"type":"base64","data":"x"}}]}]},"sessionId":"s"}
"#;
std::fs::write(tmp.join("session.jsonl"), jsonl).unwrap();
let report = audit_dir(&tmp, Corpus::ClaudeCode, None);
let dropped = report
.blocks
.get(&(
"tool_result/image".to_string(),
supercode_harness::audit::Coverage::Dropped,
))
.copied()
.expect("an unconvertible nested image must be tallied under tool_result/image: Dropped");
assert_eq!(dropped, 1);
assert!(
!report.blocks.contains_key(&(
"tool_result/image".to_string(),
supercode_harness::audit::Coverage::Normalized
)),
"an unconvertible nested image must not be miscounted as Normalized"
);
std::fs::remove_dir_all(&tmp).ok();
}
#[test]
fn fixtures_have_no_unknown_records() {
let fixtures = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("tests/fixtures");
for (file, corpus) in [
("claude_code_session.jsonl", Corpus::ClaudeCode),
("codex_session.jsonl", Corpus::Codex),
("codex_session_eventmsg.jsonl", Corpus::Codex),
("codex_session_eventmsg_precompact.jsonl", Corpus::Codex),
] {
let tmp = std::env::temp_dir().join(format!(
"sc-cov-{}-{}",
std::process::id(),
file.replace('.', "_")
));
std::fs::create_dir_all(&tmp).unwrap();
std::fs::copy(fixtures.join(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>/"))
.collect();
assert!(
unknown.is_empty(),
"{corpus:?}: unknown record discriminants: {unknown:?}"
);
std::fs::remove_dir_all(&tmp).ok();
}
}
#[test]
#[ignore = "requires local session corpus; set SUPERCODE_CORPUS=1"]
fn corpus_subdiscriminants_are_all_known() {
if std::env::var("SUPERCODE_CORPUS").is_err() {
panic!(
"SUPERCODE_CORPUS not set — this corpus test asserts nothing without \
the maintainer's local session logs; set SUPERCODE_CORPUS=1 to run it."
);
}
let home = std::env::var("HOME").unwrap();
let known_prefixes = [
"response_item/",
"event_msg/",
"session_meta",
"turn_context",
"compacted",
"user",
"assistant",
"system/",
"attachment",
"file-history-snapshot",
"file-history-delta",
"ai-title",
"permission-mode",
"mode",
"last-prompt",
"queue-operation",
"pr-link",
"frame-link",
"agent-name",
"started",
"result",
"worktree-state",
];
let known = |k: &str| known_prefixes.iter().any(|p| k.starts_with(p));
for (sub, corpus) in [
(".claude/projects", Corpus::ClaudeCode),
(".codex/sessions", Corpus::Codex),
] {
let dir = PathBuf::from(&home).join(sub);
let report = audit_dir(&dir, corpus, Some(800));
let unknown: Vec<&String> = report
.records
.keys()
.filter(|k| !k.starts_with("<line>/") && !known(k))
.collect();
assert!(
unknown.is_empty(),
"{corpus:?}: unmodeled sub-discriminants (add handling or extend the known set): {unknown:?}"
);
}
}
#[test]
#[ignore = "requires local session corpus; set SUPERCODE_CORPUS=1"]
fn corpus_has_no_unknown_record_types() {
if std::env::var("SUPERCODE_CORPUS").is_err() {
panic!(
"SUPERCODE_CORPUS not set — this corpus test asserts nothing without \
the maintainer's local session logs; set SUPERCODE_CORPUS=1 to run it."
);
}
let home = std::env::var("HOME").unwrap();
for (sub, corpus) in [
(".claude/projects", Corpus::ClaudeCode),
(".codex/sessions", Corpus::Codex),
] {
let dir = PathBuf::from(&home).join(sub);
let report = audit_dir(&dir, corpus, Some(1500));
eprintln!(
"{corpus:?}: files={} lines={} parse_errors={}",
report.files, report.lines, report.parse_errors
);
assert_eq!(report.parse_errors, 0, "{corpus:?}: typed parse errors");
let unknown: Vec<_> = report
.records
.keys()
.filter(|k| k.starts_with("<line>/"))
.collect();
assert!(
unknown.is_empty(),
"{corpus:?}: unmodeled record discriminants found: {unknown:?}"
);
}
}