///|
fn diff_load(path : String) -> @smithy.Model? raise {
  let loader = @smithy.Loader::new()
  // Reuse local resource discovery, including directory traversal and JAR
  // manifests. This runner only collects inputs; no projection or plugin runs.
  let runner = @build.BuildRunner::new(
    @build.BuildConfig::parse("{\"version\":\"1.0\"}"),
  )
  build_add_files(loader, runner, path, None) catch {
    @build.InvalidBuildConfig(message) => raise CliError(message, 1)
    error => raise error
  }
  let result = loader.assemble()
  let mut failed = result.model == None
  for event in result.validation_events() {
    if event.severity == "ERROR" || event.severity == "DANGER" {
      failed = true
    }
    if event.severity == "ERROR" ||
      event.severity == "DANGER" ||
      event.severity == "WARNING" {
      cli_stderr(path + ": " + validation_event_text(event))
    }
  }
  if failed {
    None
  } else {
    result.model
  }
}

///|
fn run_diff(
  old_path : String,
  new_path : String,
  output : String?,
  format : DiffFormat,
) -> Int32 raise {
  let old_model = diff_load(old_path)
  let new_model = diff_load(new_path)
  guard old_model is Some(old_model) && new_model is Some(new_model) else {
    return 1
  }
  let result = @diff.compare(old_model, new_model)
  if format == Jsonl {
    write_diff_jsonl(result.events, output_sink(output))
    return if result.is_breaking() { 1 } else { 0 }
  }
  let lines = result.events
    .iter()
    .filter(e => e.severity != "SUPPRESSED")
    .map(e => {
      validation_event_text(e)
      .replace_all(old="\r\n", new="\n")
      .replace_all(old="\n", new="\\n")
    })
    .collect()
  emit(if lines.is_empty() { "" } else { lines.join("\n") + "\n" }, output)
  if result.is_breaking() {
    1
  } else {
    0
  }
}