///|
pub(all) struct SourceChange {
kind : String
uri : String
} derive(ToJson)
///|
pub extend SourceChange with ToJson::{to_json}
///|
pub(all) struct DriftReport {
old_run_id : String?
new_run_id : String?
old_valid : Bool
new_valid : Bool
unchanged_count : Int
changes : Array[SourceChange]
old_diagnostics : Array[Diagnostic]
new_diagnostics : Array[Diagnostic]
} derive(ToJson)
///|
pub extend DriftReport with ToJson::{to_json}
///|
pub fn DriftReport::ok(self : DriftReport) -> Bool {
self.old_valid && self.new_valid && self.changes.is_empty()
}
///|
/// Compare captured source content by stable URI across two valid runs.
/// Changes are reported without echoing source text.
pub fn compare_jsonl(old_input : String, new_input : String) -> DriftReport {
let old_report = validate_evidence_jsonl(old_input)
let new_report = validate_evidence_jsonl(new_input)
let changes : Array[SourceChange] = []
let mut unchanged_count = 0
if old_report.ok() && new_report.ok() {
let old_contents : Map[String, String] = Map([])
let new_contents : Map[String, String] = Map([])
let old_events = parse_jsonl(old_input, [])
let new_events = parse_jsonl(new_input, [])
for event in old_events {
if event is ToolResult(_, _, true, sources, _) {
for source in sources {
if source.content is Some(content) {
old_contents.set(source.uri, content)
}
}
}
}
for event in new_events {
if event is ToolResult(_, _, true, sources, _) {
for source in sources {
if source.content is Some(content) {
new_contents.set(source.uri, content)
}
}
}
}
for source in old_report.sources {
match new_contents.get(source.uri) {
None => changes.push({ kind: "removed", uri: source.uri, })
Some(new_content) =>
match old_contents.get(source.uri) {
Some(old_content) if old_content == new_content =>
unchanged_count = unchanged_count + 1
_ => changes.push({ kind: "changed", uri: source.uri, })
}
}
}
for source in new_report.sources {
if old_contents.get(source.uri) is None {
changes.push({ kind: "added", uri: source.uri, })
}
}
}
{
old_run_id: old_report.run_id,
new_run_id: new_report.run_id,
old_valid: old_report.ok(),
new_valid: new_report.ok(),
unchanged_count,
changes,
old_diagnostics: old_report.diagnostics,
new_diagnostics: new_report.diagnostics,
}
}