///|
/// Decision audit records.
///
/// The audit operation produces the compliance-grade record for a
/// decide batch: per record the input echo (facts), the resolved
/// decision with its matched-rule evidence, engine metadata (mode,
/// rule-set digest, budget), and wall-clock-free ordering that is
/// stable across runs. Snapshots fingerprint outcomes for diffing;
/// audit preserves the full reasoning trail for reviewers who must
/// reconstruct why any single decision happened.

///|
fn audit_request(request : Value) -> Value raise {
  let mode = optional_str(get(request, "mode"), "first")
  let rules = arr(get(request, "rules"))
  let rule_digest_text = digest(canonical(get(request, "rules")))
  let budget = optional_num(get(request, "budget"), 10000.0)
  let decided = run(
    record([
      ("operation", String("decide")),
      ("rules", get(request, "rules")),
      ("facts", get(request, "facts")),
      ("mode", String(mode)),
      ("default", get(request, "default")),
      ("budget", Number(budget)),
    ]),
  )
  let facts = match get(request, "facts") {
    Array(items) => items
    other => [other]
  }
  let entries : Array[Value] = []
  match get(decided, "results") {
    Array(results) =>
      for result in results {
        let index = num(get(result, "index")).to_int()
        let outcome = get(result, "result")
        let matched : Array[Value] = []
        match get(outcome, "matched") {
          Array(items) =>
            for item in items {
              matched.push(item)
            }
          _ => ()
        }
        entries.push(
          record([
            ("index", Number(index.to_double())),
            ("facts", facts[index]),
            ("decision", get(outcome, "decision")),
            ("matched", Array(matched)),
            ("conflict", get(outcome, "conflict")),
            ("steps", get(outcome, "steps")),
          ]),
        )
      }
    _ => ()
  }
  record([
    ("engine", String("moon-policyforge")),
    ("mode", String(mode)),
    ("rule_digest", String(rule_digest_text)),
    ("rule_count", Number(rules.length().to_double())),
    ("budget", Number(budget)),
    ("record_count", Number(facts.length().to_double())),
    ("entries", Array(entries)),
  ])
}